<?php
// $Id: taxonomy_manager.admin.inc,v 1.1.2.17.2.33 2010/01/31 17:47:27 mh86 Exp $


/**
 * 
 * @file
 * Taxonomy Manager Admin
 * 
 * contains all forms and saving function for the Taxonomy Manager
 * 
 */

/**
 * list of vocabularies, which link to Taxonomy Manager interface
 */
function taxonomy_manager_voc_list() {
	$output = l ( t ( 'Add new vocabulary' ), 'admin/content/taxonomy/add/vocabulary' ) . ' | ';
	$output .= l ( t ( 'Edit vocabulary settings' ), 'admin/content/taxonomy' ) . '<br /><br />';
	
	$vocabularies = taxonomy_get_vocabularies ();
	$voc_list = array ();
	
	foreach ( $vocabularies as $vocabulary ) {
		$voc_list [] = l ( $vocabulary->name, 'admin/content/taxonomy_manager/voc/' . $vocabulary->vid );
	}
	if (! count ( $voc_list )) {
		$voc_list [] = t ( 'No Vocabularies available' );
	}
	$output .= theme ( 'item_list', $voc_list, t ( "Vocabularies:" ) );
	return $output;
}

/**
 * defines forms for taxonomy manager interface
 * 
 * @param $vid vocabulary id
 * @param $tid a term id, if not 0, displays term editing from for given tid on right side
 * @param $search_string a string to filter root level terms
 */
function taxonomy_manager_form(&$form_state, $vid, $tid = 0, $filter = NULL) {
	// Check for confirmation forms.
	if (isset ( $form_state ['confirm_delete'] )) {
		return taxonomy_manager_term_confirm_delete ( $form_state, $vid );
	}
	
	$module_path = drupal_get_path ( 'module', 'taxonomy_manager' ) . '/';
	drupal_add_css ( $module_path . 'css/taxonomy_manager.css' );
	drupal_add_js ( $module_path . 'js/hideForm.js' );
	drupal_add_js ( $module_path . 'js/updateWeight.js' );
	drupal_add_js ( $module_path . 'js/termData.js' );
	
	drupal_add_js ( array ('termData' => array ('url' => url ( "admin/content/taxonomy_manager/termdata/edit/" . $vid ), 'tid' => $tid, 'term_url' => url ( 'admin/content/taxonomy_manager/termdata/' . $vid ) ) ), 'setting' ); //TODO check if values necessary and correct
	

	drupal_add_js ( array ('updateWeight' => array ('up' => 'edit-weight-up', 'down' => 'edit-weight-down', 'url' => url ( 'admin/content/taxonomy_manager/weight/' ), 'disable_mouseover' => variable_get ( 'taxonomy_manager_disable_mouseover', 0 ) ) ), 'setting' );
	drupal_add_js ( array ('TMAjaxThrobber' => array ('add' => TRUE ) ), 'setting' );
	drupal_add_js ( array ('taxonomy_manager' => array ('modulePath' => (url ( $module_path ) == $module_path) ? $module_path : (base_path () . $module_path) ) ), 'setting' );
	
	$form = array ();
	
	$voc = taxonomy_vocabulary_load ( $vid );
	
	drupal_set_title ( t ( "Taxonomy Manager - %voc_name", array ("%voc_name" => $voc->name ) ) );
	
	if (! is_numeric ( $voc->vid )) {
		$text = t ( 'No vocabulary with this ID available! Check this <a href="!list">list</a> for available vocabularies or <a href="!create">create</a> a new one', array ('!list' => url ( 'admin/content/taxonomy_manager' ), '!create' => url ( 'admin/content/taxonomy/add/vocabulary' ) ) );
		$form ['text'] = array ('#value' => $text );
		return $form;
	}
	
	$form ['vid'] = array ('#type' => 'value', "#value" => $vid );
	
	if (_taxonomy_manager_voc_is_empty ( $vid )) {
		$text = t ( 'No terms available' );
		$form ['text'] = array ('#value' => $text );
		$form += taxonomy_manager_add_form ( $voc, FALSE );
		return $form;
	}
	
	$form ['#cache'] = TRUE;
	
	$form ['taxonomy'] ['#tree'] = TRUE;
	
	$form ['taxonomy'] ['manager'] = array ('#type' => 'fieldset', '#title' => check_plain ( $voc->name ), '#weight' => 10, '#tree' => TRUE );
	
	$form ['taxonomy'] ['manager'] ['top'] = array ('#value' => '', '#prefix' => '<div class="taxonomy-manager-tree-top">', '#suffix' => '</div>' );
	
	if (module_exists ( 'i18ntaxonomy' )) {
		if (i18ntaxonomy_vocabulary ( $vid ) == I18N_TAXONOMY_TRANSLATE) {
			if ($tid) {
				$language = _taxonomy_manager_term_get_lang ( $tid );
			} else {
				$lang = language_default ();
				$language = $lang->language;
			}
			$form ['taxonomy'] ['manager'] ['top'] ['language'] = array ('#type' => 'select', '#title' => t ( 'Language' ), '#default_value' => $language, '#options' => array ('' => t ( 'All' ), 'no language' => t ( 'no language' ) ) + locale_language_list ( 'name' ), '#attributes' => array ('class' => 'language-selector' ) );
		}
	}
	
	$form ['taxonomy'] ['manager'] ['top'] ['size'] = array ('#value' => '<div class="taxonomy-manager-tree-size">' . theme ( "image", $module_path . "images/grippie.png", t ( "Resize tree" ), t ( "Resize tree" ), array ('class' => "div-grippie" ) ) . '</div>' );
	
	$form ['taxonomy'] ['manager'] ['tree'] = array ('#type' => 'taxonomy_manager_tree', '#vid' => $vid, '#pager' => TRUE, '#search_string' => ($tid) ? NULL : $filter, '#language' => isset ( $language ) ? $language : '', '#term_to_expand' => $tid );
	
	$search_description = t ( "You can search directly for exisiting terms. 
      If your input doesn't match an existing term, it will be used for filtering root level terms (useful for non-hierarchical vocabularies)." );
	
	$form ['search'] = array ('#type' => 'fieldset', '#attributes' => array ('id' => 'taxonomy-manager-search' ), '#title' => t ( 'Search' ), '#description' => $search_description, '#collapsible' => TRUE, '#collapsed' => TRUE, '#tree' => TRUE );
	
	$form ['search'] ['field'] = array ('#type' => 'textfield', '#title' => t ( 'Search String' ), '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid, '#prefix' => '<div id="edit-find-field">', '#suffix' => '</div>' );
	
	$form ['search'] ['button'] = array ('#type' => 'submit', '#attributes' => array ('class' => 'taxonomy-manager-buttons search' ), '#value' => t ( 'Search' ), '#suffix' => '<div class="clear"></div>' );
	$search_options = array ('synonyms' => t ( 'Include synonyms' ), 'subtrees' => t ( 'Search under selected terms' ) );
	if (module_exists ( 'i18ntaxonomy' )) {
		if (i18ntaxonomy_vocabulary ( $vid ) == I18N_TAXONOMY_TRANSLATE) {
			$search_options ['language'] = t ( 'Search within selected language' );
		}
	}
	$form ['search'] ['options'] = array ('#type' => 'checkboxes', '#title' => t ( 'Search options' ), '#options' => $search_options );
	
	$form ['toolbar'] = array ('#type' => 'fieldset', '#title' => t ( 'Toolbar' ), '#attributes' => array ('id' => 'taxonomy-manager-toolbar' ) );
	
	$form ['toolbar'] ['weight_up'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons' ), '#value' => t ( 'Up' ), '#theme' => 'no_submit_button', '#prefix' => '<div id="taxonomy-manager-toolbar-buttons">' );
	
	$form ['toolbar'] ['weight-down'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons' ), '#value' => t ( 'Down' ), '#theme' => 'no_submit_button' );
	
	$form ['toolbar'] ['delete_confirm'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons delete' ), '#value' => t ( 'Delete' ), '#theme' => 'no_submit_button',
    /*'#ahah' => array(
      'path' => 'admin/content/taxonomy_manager/toolbar/form',
      'method' => 'replace',
      'event' => 'click',
      'wrapper' => 'taxonomy-manager-toolbar-forms',
      'progress' => array(),
    ),*/
  );
	
	$form ['toolbar'] ['add_show'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons add' ), '#value' => t ( 'Add' ), '#theme' => 'no_submit_button' );
	
	$form ['toolbar'] ['move_show'] = array ('#type' => 'button', '#value' => t ( 'Move' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons move' ), '#theme' => 'no_submit_button' );
	
	$form ['toolbar'] ['merge_show'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons merge' ), '#value' => t ( 'Merge' ), '#theme' => 'no_submit_button' );
	
	$form ['toolbar'] ['export_show'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons export' ), '#value' => t ( 'CSV Export' ), '#theme' => 'no_submit_button' );
	$form ['toolbar'] ['double_tree_show'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons double-tree' ), '#value' => t ( 'Double Tree' ), '#theme' => 'no_submit_button' );
	
	$form ['toolbar'] ['wrapper'] = array ('#type' => 'markup', '#value' => '<div id="taxonomy-manager-toolbar-throbber"></div><div class="clear"></div>', '#weight' => 20, '#prefix' => '</div>' );
	$form ['toolbar_forms_wrapper'] = array ('#type' => 'markup', '#value' => '<div id="taxonomy-manager-toolbar-forms"></div>' );
	
	$form += taxonomy_manager_add_form ( $voc );
	
	$form += taxonomy_manager_merge_form ( $voc );
	
	$form += taxonomy_manager_move_form ( $voc );
	
	$form += taxonomy_manager_confirm_delete ( $voc );
	
	$form += taxonomy_manager_export_form ( $voc );
	
	$form += taxonomy_manager_double_tree_settings_form ( $voc );
	
	if ($tid) {
		$form += taxonomy_manager_form_term_data ( $tid );
	} else {
		$form ['term_data'] = array ('#tree' => TRUE );
	}
	
	// add save button for term_data already to the form array, 
	// but do not render (see theme_taxonomy_manager_form) if not needed
	// otherwise an #ahah callback on dynamically added forms makes problems
	$form ['term_data'] ['save'] = array ('#type' => 'submit', '#value' => t ( 'Save changes' ), '#submit' => array ('' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons save' ), '#ahah' => array ('path' => 'admin/content/taxonomy_manager/termdata/edit', 'method' => 'replace', 'event' => 'click', 'wrapper' => 'taxonomy-term-data', 'progress' => array ('type' => '' ) ), '#weight' => 20 );
	return $form;
}

function taxonomy_manager_double_tree_form(&$form_state, $vid1, $vid2, $tid = 0, $filter = NULL) {
	// Check for confirmation forms.
	if (isset ( $form_state ['confirm_delete'] )) {
		return taxonomy_manager_term_confirm_delete ( $form_state, $vid1, $vid2 );
	}
	$module_path = drupal_get_path ( 'module', 'taxonomy_manager' ) . '/';
	
	$form = taxonomy_manager_form ( $form_state, $vid1, $tid, $filter );
	
	drupal_add_js ( array ('DoubleTree' => array ('enabled' => TRUE, 'url' => url ( 'admin/content/taxonomy_manager/double-tree/edit' ) ) ), 'setting' );
	drupal_add_js ( $module_path . 'js/doubleTree.js' );
	
	$form ['disable'] = array ('#value' => l ( t ( 'Disable Double Tree' ), 'admin/content/taxonomy_manager/voc/' . $vid1 ), '#weight' => - 100 );
	
	$voc2 = taxonomy_vocabulary_load ( $vid2 );
	$form ['vid2'] = array ('#type' => 'value', "#value" => $vid2 );
	
	$form ['taxonomy2'] = array ('#tree' => TRUE );
	
	$form ['taxonomy2'] ['manager'] = array ('#type' => 'fieldset', '#title' => check_plain ( $voc2->name ), '#weight' => 10, '#tree' => TRUE );
	
	$form ['taxonomy2'] ['manager'] ['top'] = array ('#value' => '', '#prefix' => '<div class="taxonomy-manager-tree-top">', '#suffix' => '</div>' );
	
	if (module_exists ( 'i18ntaxonomy' )) {
		if (i18ntaxonomy_vocabulary ( $vid2 ) == I18N_TAXONOMY_TRANSLATE) {
			if ($tid) {
				$language = _taxonomy_manager_term_get_lang ( $tid );
			} else {
				$lang = language_default ();
				$language = $lang->language;
			}
			$form ['taxonomy2'] ['manager'] ['top'] ['language'] = array ('#type' => 'select', '#title' => t ( 'Language' ), '#default_value' => $language, '#options' => array ('' => t ( 'All' ), 'no language' => t ( 'no language' ) ) + locale_language_list ( 'name' ), '#attributes' => array ('class' => 'language-selector' ) );
		}
	}
	
	$form ['taxonomy2'] ['manager'] ['top'] ['size'] = array ('#value' => '<div class="taxonomy-manager-tree-size">' . theme ( "image", $module_path . "images/grippie.png", t ( "Resize tree" ), t ( "Resize tree" ), array ('class' => "div-grippie" ) ) . '</div>' );
	
	$form ['taxonomy2'] ['manager'] ['tree'] = array ('#type' => 'taxonomy_manager_tree', '#vid' => $vid2, '#pager' => TRUE, '#search_string' => ($tid) ? NULL : $filter, '#language' => isset ( $language ) ? $language : '', '#term_to_expand' => $tid );
	
	$form ['double-tree'] ['operations'] = array ('#tree' => TRUE );
	$form ['double-tree'] ['operations'] ['move_right'] = array ('#type' => 'image_button', '#value' => 'Move right', '#attributes' => array ('title' => t ( 'Move right' ) ), '#src' => $module_path . "images/go-next.png", //'#executes_submit_callback' => FALSE,
'#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">', '#suffix' => '</div>' );
	$form ['double-tree'] ['operations'] ['move_left'] = array ('#type' => 'image_button', '#value' => 'Move left', '#attributes' => array ('title' => t ( 'Move left' ) ), '#src' => $module_path . "images/go-previous.png", //'#executes_submit_callback' => FALSE,
'#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">', '#suffix' => '</div>' );
	//switch operations
	if ($vid1 != $vid2) {
		$form ['double-tree'] ['operations'] ['move_right'] ['#value'] = 'Switch right';
		$form ['double-tree'] ['operations'] ['move_right'] ['#attributes'] ['title'] = t ( 'Switch selected terms and its children to the right voc' );
		$form ['double-tree'] ['operations'] ['move_left'] ['#value'] = 'Switch left';
		$form ['double-tree'] ['operations'] ['move_left'] ['#attributes'] ['title'] = t ( 'Switch selected terms and its children to the left voc' );
	} else if (isset ( $language )) {
		$form ['double-tree'] ['operations'] ['add_translation'] = array ('#type' => 'image_button', '#value' => 'translation', '#attributes' => array ('title' => t ( 'Add Translation' ) ), '#src' => $module_path . "images/connect.png", //'#executes_submit_callback' => FALSE,
'#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">', '#suffix' => '</div>' );
	}
	
	return $form;
}

function taxonomy_manager_toolbar_forms() {
	/*$params = $_GET;
  $form = array();
  $form_state = array('submitted' => FALSE);
  $form = form_get_cache($params['form_build_id'], $form_state);
  
  $form += taxonomy_manager_confirm_delete($form['vid']);
  $form = form_builder($param['form_id'], $form, $form_state);
  drupal_prepare_form($param['form_id'], $form, $form_state);
  $form = form_builder($param['form_id'], $form, $form_state);
  form_set_cache($params['form_build_id'], $form, $form_state);

  $output = drupal_render($form['delete']);
  

  print drupal_to_js(array('status' => TRUE, 'data' => $output));
  exit;*/
}

/**
 * confirmation form for deleting selected terms
 */
function taxonomy_manager_confirm_delete($voc) {
	drupal_add_js ( array ('hideForm' => array ('show_button' => 'edit-delete-confirm', 'hide_button' => 'edit-delete-cancel', 'div' => 'del-confirm-form' ) ), 'setting' );
	
	$form = array ();
	
	$form ['delete'] = array ('#type' => 'fieldset', '#attributes' => array ('id' => 'del-confirm-form', 'style' => 'display:none;' ), '#tree' => TRUE, '#title' => t ( 'Confirmation' ) );
	
	$question = t ( 'Are you sure you want to delete all selected terms? ' );
	$info = t ( 'Remember all term specific data will be lost. This action cannot be undone.' );
	
	$form ['delete'] ['text'] = array ('#value' => "<b>" . $question . "</b><br/>" . $info );
	
	$options = array ('delete_orphans' => t ( 'Delete children of selected terms, if there are any' ) );
	
	$form ['delete'] ['options'] = array ('#type' => 'checkboxes', '#title' => t ( 'Options' ), '#options' => $options );
	
	$form ['delete'] ['delete'] = array ('#type' => 'submit', '#value' => t ( 'Delete' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons delete' ), '#submit' => array ('taxonomy_manager_form_delete_submit' ), '#validate' => array ('taxonomy_manager_form_delete_validate' ) );
	
	$form ['delete'] ['cancel'] = array ('#type' => 'button', '#attributes' => array ('class' => 'taxonomy-manager-buttons cancel' ), '#value' => t ( 'Cancel' ), '#theme' => 'no_submit_button' );
	
	return $form;
}

/**
 * form for adding terms
 */
function taxonomy_manager_add_form($voc, $hide_form = TRUE) {
	if ($hide_form) {
		drupal_add_js ( array ('hideForm' => array ('show_button' => 'edit-add-show', 'hide_button' => 'edit-add-cancel', 'div' => 'add-form' ) ), 'setting' );
		$attributes = array ('id' => 'add-form', 'style' => 'display:none;' );
	} else {
		$attributes = array ('id' => 'add-form' );
	}
	
	$form = array ();
	
	$description = "";
	$description = t ( "If you have selected one or more terms in the tree view, the new terms are automatically children of those." );
	
	//TODO: add info user	
	$form ['add'] = array ('#type' => 'fieldset', '#tree' => TRUE, '#attributes' => $attributes, '#title' => t ( 'Thêm thành viên' ), '#description' => $description );
	$form ['add'] ['term'] ['name'] = array ('#type' => 'textfield', '#title' => t ( 'Tên đăng nhập' ) );
	$form ['add'] ['user'] ['user_nguoigioithieu'] = array ('#type' => 'textfield', '#title' => t ( 'Người giới thiệu' ), '#autocomplete_path' => 'user/autocomplete' );
	$form ['add'] ['user'] ['mail'] = array ('#type' => 'textfield', '#title' => t ( 'Email' ), '#maxlength' => USERNAME_MAX_LENGTH, '#size' => 60 );
	$form ['add'] ['user'] ['pass'] = array ('#type' => 'textfield', '#title' => t ( 'Mật khẩu' ), '#maxlength' => USERNAME_MAX_LENGTH, '#size' => 60 );
	$form ['add'] ['user'] ['user_tendaydu'] = array ('#type' => 'textfield', '#title' => t ( 'Họ và tên' ) );
	$form ['add'] ['user'] ['user_birthday'] = array ('#type' => 'date', '#title' => t ( 'Ngày tháng năm sinh' ) );
	$form ['add'] ['user'] ['user_dienthoai'] = array ('#type' => 'textfield', '#title' => t ( 'Điện thoại liên hệ' ) );
	$form ['add'] ['user'] ['user_diachi'] = array ('#type' => 'textfield', '#title' => t ( 'Địa chỉ' ) );
	$form ['add'] ['user'] ['user_quoctich'] = array ('#type' => 'textfield', '#title' => t ( 'Quốc tịch' ), '#autocomplete_path' => 'taxonomy_manager/autocomplete/2' );
	$form ['add'] ['user'] ['user_dantoc'] = array ('#type' => 'textfield', '#title' => t ( 'Dân tộc' ), '#autocomplete_path' => 'taxonomy_manager/autocomplete/3' );
	$form ['add'] ['user'] ['user_socmt'] = array ('#type' => 'textfield', '#title' => t ( 'Số chứng minh' ) );
	$form ['add'] ['user'] ['user_ngaycap'] = array ('#type' => 'date', '#title' => t ( 'Ngày cấp' ) );
	$form ['add'] ['user'] ['user_noicap'] = array ('#type' => 'textfield', '#title' => t ( 'Nơi cấp' ) );
	
	$form ['add'] ['mass'] = array ('#type' => 'fieldset', '#tree' => TRUE, '#title' => t ( 'Mass term import (with textarea)' ), '#collapsible' => TRUE, '#collapsed' => TRUE );
	$form ['add'] ['mass'] ['mass_add'] = array ('#type' => 'textarea', '#title' => t ( 'Terms' ), '#description' => t ( 'One term per line' ), '#rows' => 10 );
	$form ['add'] ['add'] = array ('#type' => 'submit', '#attributes' => array ('class' => 'taxonomy-manager-buttons add' ), '#value' => t ( 'Add' ), '#validate' => array ('taxonomy_manager_form_add_validate' ), '#submit' => array ('taxonomy_manager_form_add_submit' ) );
	$form ['add'] ['cancel'] = array ('#type' => 'button', '#value' => t ( 'Cancel' ), '#theme' => 'no_submit_button', '#attributes' => array ('class' => 'taxonomy-manager-buttons cancel' ) );
	
	return $form;

}

/**
 * form for merging terms
 */
function taxonomy_manager_merge_form($voc) {
	drupal_add_js ( array ('hideForm' => array ('show_button' => 'edit-merge-show', 'hide_button' => 'edit-merge-cancel', 'div' => 'merge-form' ) ), 'setting' );
	
	$form = array ();
	
	$description .= t ( "The selected terms get merged into one term. 
    This resulting merged term can either be an exisiting term or a completely new term. 
    The selected terms will automatically get synomyms of the merged term and will be deleted afterwards." );
	
	$form ['merge'] = array ('#type' => 'fieldset', '#tree' => TRUE, '#attributes' => array ('id' => 'merge-form', 'style' => 'display:none;' ), '#title' => t ( 'Merging of terms' ), '#description' => $description );
	
	$form ['merge'] ['main_term'] = array ('#type' => 'textfield', '#title' => t ( 'Resulting merged term' ), '#description' => t ( "Enter a unique term name or a term id with 'term-id:[tid]'" ), '#required' => FALSE, '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid );
	
	$options = array ();
	
	$options ['collect_parents'] = t ( 'Collect all parents of selected terms an add it to the merged term' );
	$options ['collect_children'] = t ( 'Collect all children of selected terms an add it to the merged term' );
	$options ['collect_relations'] = t ( 'Collect all relations of selected terms an add it to the merged term' );
	
	if (count ( $options ) > 0) {
		$form ['merge'] ['options'] = array ('#type' => 'checkboxes', '#title' => t ( 'Options' ), '#options' => $options );
	}
	
	$form ['merge'] ['submit'] = array ('#type' => 'submit', '#value' => t ( 'Merge' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons merge' ), '#validate' => array ('taxonomy_manager_form_merge_validate' ), '#submit' => array ('taxonomy_manager_form_merge_submit' ) );
	
	$form ['merge'] ['cancel'] = array ('#type' => 'button', '#value' => t ( 'Cancel' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons cancel' ), '#theme' => 'no_submit_button' );
	
	return $form;
}

/**
 * form for moving terms in hierarchies
 */
function taxonomy_manager_move_form($voc) {
	drupal_add_js ( array ('hideForm' => array ('show_button' => 'edit-move-show', 'hide_button' => 'edit-move-cancel', 'div' => 'move-form' ) ), 'setting' );
	
	$form = array ();
	
	$description = t ( "You can change the parent of one or more selected terms. 
      If you leave the autocomplete field empty, the term will be a root term." );
	
	$form ['move'] = array ('#type' => 'fieldset', '#tree' => TRUE, '#attributes' => array ('id' => 'move-form', 'style' => 'display:none;' ), '#title' => t ( 'Moving of terms' ), '#description' => $description );
	
	$form ['move'] ['parents'] = array ('#type' => 'textfield', '#title' => t ( 'Parent term(s)' ), '#description' => t ( "Enter a unique term name or a term id with 'term-id:[tid]'. Separate multiple parent terms with commas." ), '#required' => FALSE, '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid );
	
	$options = array ();
	$options ['keep_old_parents'] = t ( 'Keep old parents and add new ones (multi-parent). Otherwise old parents get replaced.' );
	$form ['move'] ['options'] = array ('#type' => 'checkboxes', '#title' => t ( 'Options' ), '#options' => $options );
	
	$form ['move'] ['submit'] = array ('#type' => 'submit', '#attributes' => array ('class' => 'taxonomy-manager-buttons move' ), '#value' => t ( 'Move' ), '#validate' => array ('taxonomy_manager_form_move_validate' ), '#submit' => array ('taxonomy_manager_form_move_submit' ) );
	
	$form ['move'] ['cancel'] = array ('#type' => 'button', '#value' => t ( 'Cancel' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons cancel' ), '#theme' => 'no_submit_button' );
	
	return $form;
}

/**
 * form for exporting terms
 */
function taxonomy_manager_export_form($voc) {
	drupal_add_js ( array ('hideForm' => array ('show_button' => 'edit-export-show', 'hide_button' => 'edit-export-cancel', 'div' => 'export-form' ) ), 'setting' );
	
	$module_path = drupal_get_path ( 'module', 'taxonomy_manager' ) . '/';
	drupal_add_js ( $module_path . 'js/csv_export.js' );
	
	drupal_add_js ( array ('exportCSV' => array ('url' => url ( "admin/content/taxonomy_manager/export" ) ) ), 'setting' );
	
	$form = array ();
	
	$form ['export'] = array ('#type' => 'fieldset', '#tree' => TRUE, '#attributes' => array ('id' => 'export-form', 'style' => 'display:none;' ), '#title' => t ( 'CSV Export' ), '#description' => $description );
	
	$form ['export'] ['delimiter'] = array ('#type' => 'textfield', '#title' => t ( 'Delimiter for CSV File' ), '#required' => FALSE, '#default_value' => ";" );
	
	$options ['whole_voc'] = t ( 'Whole Vocabulary' );
	$options ['children'] = t ( 'Child terms of a selected term' );
	$options ['root_terms'] = t ( 'Root level terms only' );
	
	$form ['export'] ['options'] = array ('#type' => 'radios', '#title' => t ( 'Terms to export' ), '#options' => $options, '#default_value' => 'whole_voc', '#prefix' => '<div id="taxonomy_manager_export_options">', '#suffix' => '</div>' );
	
	$form ['export'] ['depth'] = array ('#type' => 'textfield', '#title' => t ( 'Depth of tree' ), '#description' => t ( 'The number of levels of the tree to export. Leave empty to return all levels.' ) );
	
	$form ['export'] ['csv'] = array ('#type' => 'textarea', '#title' => t ( 'Exported CSV' ), '#description' => t ( 'The generated code will appear here (per AJAX). You can copy and paste the code into a .csv file. The csv has following columns: voc id | term id | term name | description | parent id 1 | ... | parent id n' ), '#rows' => 8 );
	
	$form ['export'] ['submit'] = array ('#type' => 'submit', '#attributes' => array ('class' => 'taxonomy-manager-buttons export' ), '#value' => t ( 'Export now' ), '#theme' => 'no_submit_button' );
	
	$form ['export'] ['cancel'] = array ('#type' => 'button', '#value' => t ( 'Cancel' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons cancel' ), '#theme' => 'no_submit_button' );
	
	return $form;
}

function taxonomy_manager_double_tree_settings_form($voc) {
	drupal_add_js ( array ('hideForm' => array ('show_button' => 'edit-double-tree-show', 'hide_button' => 'edit-double-tree-cancel', 'div' => 'double-tree-settings-form' ) ), 'setting' );
	
	$form = array ();
	
	$form ['double_tree'] = array ('#type' => 'fieldset', '#tree' => TRUE, '#attributes' => array ('id' => 'double-tree-settings-form', 'style' => 'display:none;' ), '#title' => t ( 'Double Tree Settings' ), '#description' => t ( 'Specify settings for second tree. Choose the same vocabulary if you want to move terms in the hierarchy or if you want to add new translations within a multilingual vocabulary. Choose a different vocabulary if you want to switch terms among these vocabularies.' ) );
	
	$options = array ();
	$vocs = taxonomy_get_vocabularies ();
	foreach ( $vocs as $v ) {
		$options [$v->vid] = $v->name;
	}
	$form ['double_tree'] ['voc2'] = array ('#type' => 'select', '#title' => t ( 'Vocabulary for second tree' ), '#options' => $options, '#default_value' => $voc->vid );
	
	$form ['double_tree'] ['submit'] = array ('#type' => 'submit', '#attributes' => array ('class' => 'taxonomy-manager-buttons double-tree' ), '#value' => t ( 'Enable Double Tree' ), '#submit' => array ('taxonomy_manager_form_double_tree_submit' ) );
	if (arg ( 3 ) == "double-tree") {
		$form ['double_tree'] ['disable'] = array ('#type' => 'submit', '#attributes' => array ('class' => 'taxonomy-manager-buttons double-tree-disable' ), '#value' => t ( 'Disable Double Tree' ), '#submit' => array ('taxonomy_manager_form_double_tree_disable_submit' ) );
	}
	$form ['double_tree'] ['cancel'] = array ('#type' => 'button', '#value' => t ( 'Cancel' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons cancel' ), '#theme' => 'no_submit_button' );
	
	return $form;
}

/**
 * menu callback for displaying term data form
 * 
 * if this function gets called by ahah, then the term data form gets 
 * generated, rendered and return
 * otherwise, if no ahah call, redirect to original form with $vid and $tid as parameters
 *
 * @param $vid
 * @param $tid
 * @param $ahah if true, return rendered form, else redirect
 */
function taxonomy_manager_update_term_data_form($vid, $tid, $ahah = FALSE, $print = TRUE, $msg = "", $is_error_msg = FALSE) {
	if (! $ahah) {
		drupal_goto ( 'admin/content/taxonomy_manager/voc/' . $vid . '/' . $tid );
	}
	$GLOBALS ['devel_shutdown'] = FALSE; //prevent devel queries footprint
	

	$params = $_GET;
	
	//actually we don not need do use the caching because the saving only happens through a AJAX callback
	//and it's a bit faster, cache loading, form building and cache saving needs some time else.
	/*$form_state = array('submitted' => FALSE);
  $form = form_get_cache($params['form_build_id'], $form_state);
  unset($form['term_data']);
  $form = form_builder($param['form_id'], $form, $form_state);*/
	
	$term_form = taxonomy_manager_form_term_data ( $tid );
	$term_form ['term_data'] ['save'] = array ('#type' => 'submit', '#value' => t ( 'Save changes' ), '#submit' => array ('' ), '#attributes' => array ('class' => 'taxonomy-manager-buttons save' ), '#ahah' => array ('path' => 'admin/content/taxonomy_manager/termdata/edit', 'method' => 'replace', 'event' => 'click', 'wrapper' => 'taxonomy-term-data', 'progress' => array ('type' => '' ) ), '#weight' => 20 );
	if ($msg != "") {
		$term_form ['term_data'] ['msg'] = array ('#type' => 'markup', '#prefix' => '<div class="messages status">', '#suffix' => '</div>', '#value' => $msg, '#weight' => - 20 );
		if ($is_error_msg) {
			$term_form ['term_data'] ['msg'] ['#value'] = t ( "Error! Your last operation couldn't be performed because of following problem:" ) . " " . $msg;
			$term_form ['term_data'] ['msg'] ['#prefix'] = '<div class="message error">';
		}
	}
	$form = $term_form;
	
	drupal_prepare_form ( 'taxonomy_manager_form', $form, $form_state );
	$form = form_builder ( 'taxonomy_manager_form', $form, $form_state );
	//form_set_cache($params['form_build_id'], $form, $form_state);
	

	$output = drupal_render ( $form ['term_data'] );
	
	if ($print) {
		print $output;
		exit ();
	}
	return $output;
}

/**
 * term data editing form
 *
 * @param $tid
 */
function taxonomy_manager_form_term_data($tid) {
	$term = taxonomy_get_term ( $tid );
	include_once '/' . drupal_get_path ( 'module', 'user' ) . '/user.module';
	//user_edit($account);
	$user = db_fetch_object ( db_query ( "SELECT * FROM {users} as u INNER JOIN {profile_values} as p ON u.uid = p.uid
INNER JOIN {profile_fields} as pf ON p.fid = pf.fid WHERE u.name = '%s'", $term->name ) );
	
	echo 'SELECT * FROM {users} as u INNER JOIN {profile_values} as p ON u.uid = p.uid
INNER JOIN {profile_fields} as pf ON p.fid = pf.fid WHERE u.name = ' . $term->name;
	print_r ( $user );
	
	die ();
	$module_path = drupal_get_path ( 'module', 'taxonomy_manager' ) . '/';
	$vocabulary = taxonomy_vocabulary_load ( $term->vid );
	
	//prevent that title of the fieldset is too long
	$title = $term->name;
	if (drupal_strlen ( $title ) >= 33) {
		$title = drupal_substr ( $title, 0, 33 ) . "...";
	}
	$title .= " (" . $term->tid . ")";
	$title = check_plain ( $title );
	
	$form ['term_data'] = array ('#type' => 'fieldset', '#title' => $title, '#attributes' => array ('id' => 'taxonomy-term-data-fieldset' ), '#tree' => TRUE );
	
	$form ['term_data'] ['close'] = array ('#value' => '<div id="term-data-close"><span title="' . t ( 'Close' ) . '">&nbsp;&nbsp;&nbsp;&nbsp;</span></div>', '#weight' => - 100 );
	
	$form ['term_data'] ['tid'] = array ('#type' => 'hidden', '#value' => $tid );
	
	$form ['term_data'] ['name'] = array ('#type' => 'textfield', '#title' => t ( 'Tên đăng nhập' ), '#default_value' => $term->name, '#size' => 35, '#maxlength' => 255, '#required' => TRUE, '#weight' => - 20 );
	
	$form ['term_data'] ['user'] ['uid'] = array ('#type' => 'hidden', '#default_value' => $user->uid );
	$form ['term_data'] ['user'] ['name'] = array ('#type' => 'hidden', '#default_value' => $user->name );
	$form ['term_data'] ['user'] ['mail'] = array ('#type' => 'textfield', '#title' => t ( 'Email' ), '#default_value' => $user->mail, '#maxlength' => USERNAME_MAX_LENGTH, '#size' => 60 );
	$form ['term_data'] ['user'] ['pass'] = array ('#type' => 'textfield', '#title' => t ( 'Mật khẩu' ), '#default_value' => null, '#maxlength' => USERNAME_MAX_LENGTH, '#size' => 60 );
	$form ['term_data'] ['user'] ['user_tendaydu'] = array ('#type' => 'textfield', '#default_value' => $user->user_tendaydu, '#title' => t ( 'Họ và tên' ) );
	$form ['term_data'] ['user'] ['user_birthday'] = array ('#type' => 'date', '#default_value' => $user->user_birthday, '#title' => t ( 'Ngày tháng năm sinh' ) );
	$form ['term_data'] ['user'] ['user_dienthoai'] = array ('#type' => 'textfield', '#default_value' => $user->user_dienthoai, '#title' => t ( 'Điện thoại liên hệ' ) );
	$form ['term_data'] ['user'] ['user_diachi'] = array ('#type' => 'textfield', '#default_value' => $user->user_diachi, '#title' => t ( 'Địa chỉ' ) );
	$form ['term_data'] ['user'] ['user_quoctich'] = array ('#type' => 'textfield', '#default_value' => $user->user_quoctich, '#title' => t ( 'Quốc tịch' ) );
	$form ['term_data'] ['user'] ['user_dantoc'] = array ('#type' => 'textfield', '#default_value' => $user->user_dantoc, '#title' => t ( 'Dân tộc' ) );
	$form ['term_data'] ['user'] ['user_socmt'] = array ('#type' => 'textfield', '#default_value' => $user->user_socmt, '#title' => t ( 'Số chứng minh' ) );
	$form ['term_data'] ['user'] ['user_ngaycap'] = array ('#type' => 'date', '#default_value' => $user->user_ngaycap, '#title' => t ( 'Ngày cấp' ) );
	$form ['term_data'] ['user'] ['user_noicap'] = array ('#type' => 'textfield', '#default_value' => $user->user_noicap, '#title' => t ( 'Nơi cấp' ) );
	$form ['term_data'] ['description'] = array ('#type' => 'textarea', '#title' => t ( 'Mô tả' ), '#default_value' => $term->description, '#cols' => 35, '#rows' => 3 );
	
	$synonyms = taxonomy_get_synonyms ( $term->tid );
	asort ( $synonyms );
	
	$form ['term_data'] ['vid'] = array ('#type' => 'hidden', '#value' => $term->vid );
	
	return $form;
}

/**
 * helper function for generating tables with values and delete op and field for adding
 *
 * @param $term term object which is going to be displayed
 * @param $values array of values to show, e.g related terms, synonyms, parents, children
 * @param $header_type string to display as header
 * @param $attr attribute type to show, can be 'related', 'synonym', 'parent', 'child'
 * @param $autocomplete if true, adds autocomplete, else a textfield
 * @param $add if true, shows add operation
 * @return an form array
 */
function _taxonomy_manager_form_term_data_lists($term, $values, $header_type, $attr, $autocomplete = TRUE, $add = TRUE) {
	$module_path = drupal_get_path ( 'module', 'taxonomy_manager' ) . '/';
	$rows = array ();
	
	$form ['#theme'] = 'taxonomy_manager_term_data_extra';
	$form ['data'] = array ();
	foreach ( $values as $tid => $value ) {
		if (is_object ( $value )) {
			$name = $value->name;
			$id = $value->tid;
			$vid = $value->vid;
			$extra_info = taxonomy_manager_tree_term_extra_info ( $value );
		} else {
			$name = $value;
			$id = $value;
		}
		$form ['data'] [$id] [] = array ('#value' => (isset ( $vid ) && $vid > 0) ? l ( $name, 'admin/content/taxonomy_manager/termdata/' . $vid . "/" . $id, array ('attributes' => array ('title' => $extra_info, 'class' => 'taxonomy-term-data-name-link' ) ) ) : check_plain ( $name ), '#row-class' => 'taxonomy-term-data-name', '#row-id' => 'term-' . $id );
		$form ['data'] [$id] [] = array ('#value' => '<span class="' . $attr . '" title="' . t ( 'Remove' ) . '">&nbsp;</span>', '#row-class' => 'taxonomy-term-data-operations' );
	}
	$form ['headers'] [] = array ('#value' => $header_type );
	$form ['headers'] [] = array ('#value' => '' );
	
	$form ['op'] = array ();
	if ($add) {
		$form ['op'] ['add'] = array ('#type' => 'textfield', '#prefix' => '<div class="term-data-autocomplete">', '#suffix' => '</div>', '#size' => 35 );
		if ($autocomplete) {
			$form ['op'] ['add'] ['#autocomplete_path'] = 'taxonomy_manager/autocomplete/' . $term->vid;
		}
		
		$form ['op'] ['add_button'] = array ('#value' => '<span class="' . $attr . '" title="' . t ( 'Add' ) . '">&nbsp;</span>', '#prefix' => '<div class="term-data-autocomplete-add">', '#suffix' => '</div>' );
	}
	
	return $form;

}

/**
 * helper function for generating a table listing the translations 
 */
function _taxonomy_manager_form_term_data_translations($term, $translations, $header_type, $attr, $autocomplete = TRUE, $add = TRUE) {
	$module_path = drupal_get_path ( 'module', 'taxonomy_manager' ) . '/';
	$rows = array ();
	
	$form ['#theme'] = 'taxonomy_manager_term_data_extra';
	$form ['data'] = array ();
	
	foreach ( $translations as $tid => $value ) {
		if (is_object ( $value )) {
			$name = $value->name;
			$id = $value->tid;
			$vid = $value->vid;
			$lang = $value->language;
			$trid = $value->trid;
			$extra_info = taxonomy_manager_tree_term_extra_info ( $value );
		}
		$form ['data'] [$id] [] = array ('#value' => (isset ( $vid ) && $vid > 0) ? l ( $name, 'admin/content/taxonomy_manager/termdata/' . $vid . "/" . $id, array ('attributes' => array ('title' => $extra_info ) ) ) : check_plain ( $name ), '#row-class' => 'taxonomy-term-data-name', '#row-id' => 'term-' . $id );
		$form ['data'] [$id] [] = array ('#value' => check_plain ( locale_language_name ( $lang ) ), '#row-class' => 'taxonomy-term-data-lang', '#row-id' => 'term-lang-' . $id );
		$form ['data'] [$id] [] = array ('#value' => '<span class="' . $attr . '" title="' . t ( 'Remove' ) . '">&nbsp;</span>', '#row-class' => 'taxonomy-term-data-operations' );
	}
	$form ['headers'] [] = array ('#value' => $header_type );
	$form ['headers'] [] = array ('#value' => t ( 'Language' ) );
	$form ['headers'] [] = array ('#value' => '' );
	
	$form ['op'] = array ();
	if ($add) {
		$form ['op'] ['add'] = array ('#type' => 'textfield', '#prefix' => '<div class="term-data-autocomplete">', '#suffix' => '</div>', '#size' => 35 );
		$form ['op'] ['lang'] = array ('#type' => 'select', '#options' => array ('' => '' ) + locale_language_list ( 'name' ), '#default value' => '' );
		if ($autocomplete) {
			$form ['op'] ['add'] ['#autocomplete_path'] = 'taxonomy_manager/autocomplete/' . $term->vid;
		}
		
		$form ['op'] ['add_button'] = array ('#value' => '<span class="' . $attr . '" title="' . t ( 'Add' ) . '">&nbsp;</span>', '#prefix' => '<div class="term-data-autocomplete-add">', '#suffix' => '</div>' );
	}
	
	return $form;

}

/**
 * validates the form (only search button)
 **/
function taxonomy_manager_form_validate($form, &$form_state) {
	if ($form_state ['clicked_button'] ['#value'] == t ( 'Search' ) && empty ( $form_state ['values'] ['search'] ['field'] )) {
		form_set_error ( 'search', t ( 'Search field is empty' ) );
		$form_state ['rebuild'] = TRUE;
	}
}

/**
 * submits the taxonomy manager form (only search button)
 **/
function taxonomy_manager_form_submit($form, &$form_state) {
	
	if ($form_state ['values'] ['delete'] === TRUE) {
		return taxonomy_manager_term_confirm_delete_submit ( $form, $form_state );
	}
	if (isset ( $form_state ['values'] ['vid2'] )) {
		$url_prefix = 'admin/content/taxonomy_manager/double-tree/' . $form_state ['values'] ['vid'] . '/' . $form_state ['values'] ['vid2'];
	} else {
		$url_prefix = 'admin/content/taxonomy_manager/voc/' . $form_state ['values'] ['vid'];
	}
	
	$search_string = $form_state ['values'] ['search'] ['field'];
	$terms = array ();
	
	$include_synonyms = FALSE;
	$selected_tids = array ();
	
	if ($form_state ['values'] ['search'] ['options'] ['synonyms']) {
		$include_synonyms = TRUE;
	}
	if ($form_state ['values'] ['search'] ['options'] ['subtrees']) {
		$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	}
	if ($form_state ['values'] ['search'] ['options'] ['language']) {
		$language = $form_state ['values'] ['taxonomy'] ['manager'] ['top'] ['language'];
	}
	
	$terms = taxonomy_manager_autocomplete_search_terms ( $search_string, $form_state ['values'] ['vid'], $include_synonyms, $selected_tids, $language );
	if (count ( $terms ) == 1) {
		$tid = $terms [0];
		drupal_set_message ( t ( "Your search string matches exactly one term" ) );
		drupal_goto ( $url_prefix . '/' . $tid );
	} else if (count ( $terms ) > 1) {
		$matched_text_list = array ();
		foreach ( $terms as $matched_tid ) {
			$matched_term = taxonomy_get_term ( $matched_tid );
			$parents = array ();
			foreach ( taxonomy_get_parents ( $matched_tid ) as $parent ) {
				$parents [] = check_plain ( $parent->name );
			}
			$parent_text = count ( $parents ) ? implode ( ' | ', $parents ) . " › " : "";
			$term = taxonomy_get_term ( $t ['tid'] );
			$matched_text_list [] = $parent_text . "" . l ( $matched_term->name, $url_prefix . '/' . $matched_term->tid, array ('attributes' => array ('title' => taxonomy_manager_tree_term_extra_info ( $matched_term ) ) ) ) . " (" . $matched_term->tid . (! empty ( $matched_term->language ) ? '-' . check_plain ( $matched_term->language ) : '') . ")";
		}
		drupal_set_message ( t ( "Your search string matches !count terms:", array ('!count' => count ( $terms ) ) ) . "" . theme ( 'item_list', $matched_text_list ) );
		$form_state ['rebuild'] = TRUE;
	} else {
		drupal_set_message ( t ( "No match found. Filtering root level terms starting with @search_string.", array ('@search_string' => $search_string ) ) );
		drupal_set_message ( l ( t ( "Show unfiltered tree" ), $url_prefix ) );
		drupal_goto ( $url_prefix . '/0/' . $search_string );
	}
}

/**
 * validates taxonomy manager double tree
 **/
function taxonomy_manager_double_tree_form_validate($form, &$form_state) {
	return taxonomy_manager_form_validate ( $form, $form_state );
}

/**
 * submits the taxonomy manager double tree
 **/
function taxonomy_manager_double_tree_form_submit($form, &$form_state) {
	return taxonomy_manager_form_submit ( $form, $form_state );
}

/**
 * Submit handler for adding terms
 */

function taxonomy_manager_to_user($userinfo) {
	include_once '/' . drupal_get_path ( 'module', 'user' ) . '/user.module';
	$timezone = variable_get ( 'date_default_timezone', NULL );
	$userinfo ['values'] ['status'] = 1;
	$userinfo ['values'] ['timezone'] = $timezone;
	$userinfo ['values'] ['form_build_id'] = null;
	$userinfo ['values'] ['init'] = $userinfo ['mail'];
	$userinfo ['values'] ['created'] = time ();
	$userinfo ['values'] ['access'] = time ();
	user_register_submit ( '', $userinfo );
}

function taxonomy_manager_form_add_submit($form, &$form_state) {
	$a = array ('name' => $form_state ['values'] ['add'] ['term'] ['name'] );
	$userinfo = $form_state ['values'] ['add'] ['user'];
	$b ['values'] = $a + $userinfo;
	
	foreach ( $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'] as $t ) {
		$b ['values'] ['user_parent'] = $t;
	}
	
	taxonomy_manager_to_user ( $b );
	
	$terms = array ();
	$selected_tids = array ();
	$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	foreach ( $form_state ['values'] ['add'] ['term'] as $value ) {
		if (! empty ( $value )) {
			$terms [] = $value;
		}
	}
	if ($form_state ['values'] ['add'] ['mass'] ['mass_add']) {
		foreach ( explode ( "\n", str_replace ( "\r", '', $form_state ['values'] ['add'] ['mass'] ['mass_add'] ) ) as $term ) {
			if ($term) {
				$terms [] = $term;
			}
		}
	}
	foreach ( $terms as $name ) {
		$term = array ();
		$term ['name'] = $name;
		$term ['vid'] = $form_state ['values'] ['vid'];
		$term ['parent'] = $selected_tids;
		taxonomy_save_term ( $term );
		if (module_exists ( 'i18ntaxonomy' )) {
			if (i18ntaxonomy_vocabulary ( $form_state ['values'] ['vid'] ) == I18N_TAXONOMY_TRANSLATE && $form_state ['values'] ['taxonomy'] ['manager'] ['top'] ['language'] != "") {
				_i18ntaxonomy_term_set_lang ( $term ['tid'], $form_state ['values'] ['taxonomy'] ['manager'] ['top'] ['language'] );
				$updated_lang = TRUE;
			}
		}
	}
	taxonomy_manager_update_voc ( $form_state ['values'] ['vid'], $selected_tids );
	
	if (isset ( $updated_lang ) && $updated_lang == TRUE) {
		drupal_set_message ( t ( "Saving terms to language @lang", array ('@lang' => locale_language_name ( $form_state ['values'] ['taxonomy'] ['manager'] ['top'] ['language'] ) ) ) );
	}
	drupal_set_message ( t ( "Thêm thành viên : %terms thành công", array ('%terms' => implode ( ', ', $terms ) ) ) );
}

/**
 * Validation handler for deleting terms
 */
function taxonomy_manager_form_delete_validate($form, &$form_state) {
	$selected_tids = array ();
	$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	if (count ( $selected_tids ) < 1) {
		form_set_error ( 'delete', t ( "No terms for deleting selected" ) );
		$form_state ['rebuild'] = TRUE;
	}
}

/**
 * Submit handler for deleting terms
 */
function taxonomy_manager_form_delete_submit($form, &$form_state) {
	$selected_tids = array ();
	$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	if ($form_state ['values'] ['delete'] === TRUE) {
		return taxonomy_manager_term_confirm_delete_submit ( $form, $form_state );
	}
	// Rebuild the form to confirm term deletion.
	$form_state ['rebuild'] = TRUE;
	$form_state ['confirm_delete'] = TRUE;
}

/**
 * Form builder for the term delete form.
 *
 */
function taxonomy_manager_term_confirm_delete(&$form_state, $vid, $vid2 = NULL) {
	if (isset ( $vid2 )) {
		$form ['vid2'] = array ('#type' => 'value', '#value' => $vid2 );
		$url = 'admin/content/taxonomy_manager/double-tree/' . $vid . '/' . $vid2;
	} else {
		$url = 'admin/content/taxonomy_manager/voc/' . $vid;
	}
	$selected = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	$form ['selected_terms'] = array ('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE );
	foreach ( $selected as $tid ) {
		$term = taxonomy_get_term ( $tid );
		$form ['selected_terms'] [$tid] = array ('#type' => 'hidden', '#value' => $tid, '#prefix' => '<li>', '#suffix' => check_plain ( $term->name ) . "</li>\n" );
	}
	
	$form ['delete'] = array ('#type' => 'value', '#value' => TRUE );
	$form ['vid'] = array ('#type' => 'value', '#value' => $vid );
	$form ['options'] = array ('#type' => 'value', '#value' => $form_state ['values'] ['delete'] ['options'] );
	$msg = ! empty ( $form_state ['values'] ['delete'] ['options'] ['delete_orphans'] ) ? t ( 'Deleting a term will delete all its children if there are any. ' ) : '';
	$msg .= t ( 'This action cannot be undone.' );
	return confirm_form ( $form, t ( 'Are you sure you want to delete the following terms: ' ), $url, $msg, t ( 'Delete' ), t ( 'Cancel' ) );
}

/**
 * Submit handler to delete a term after confirmation.
 *
 */
function taxonomy_manager_term_confirm_delete_submit($form, &$form_state) {
	taxonomy_manager_delete_terms ( $form_state ['values'] ['selected_terms'], $form_state ['values'] ['options'] );
	if (isset ( $form_state ['values'] ['vid2'] )) {
		$form_state ['redirect'] = 'admin/content/taxonomy_manager/double-tree/' . $form_state ['values'] ['vid'] . '/' . $form_state ['values'] ['vid2'];
	} else {
		$form_state ['redirect'] = 'admin/content/taxonomy_manager/voc/' . $form_state ['values'] ['vid'];
	}
	drupal_set_message ( t ( "Selected terms deleted" ) );
	return;
}

/**
 * Validation handler for moving terms
 */
function taxonomy_manager_form_move_validate($form, &$form_state) {
	$selected_tids = array ();
	$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	$error_msg = "";
	if (count ( $selected_tids ) < 1) {
		form_set_error ( 'move', t ( "Please selected terms you want to move in the hierarchy" ) );
		$form_state ['rebuild'] = TRUE;
	} else if (_taxonomy_manager_check_duplicates ( $form_state ['values'] ['vid'], $form_state ['values'] ['move'] ['parents'], $error_msg )) {
		form_set_error ( 'move', t ( "Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'" ) . " (" . $error_msg . ")." );
		$form_state ['rebuild'] = TRUE;
	}
	
	$typed_parents = taxonomy_manager_autocomplete_tags_get_tids ( $form_state ['values'] ['move'] ['parents'], $form_state ['values'] ['vid'], FALSE );
	
	$parents = array ();
	foreach ( $typed_parents as $parent_info ) {
		$parents [( int ) $parent_info ['tid']] = ( int ) $parent_info ['tid'];
	}
	
	if (! taxonomy_manager_check_circular_hierarchy ( $selected_tids, $parents )) {
		form_set_error ( 'move', t ( 'Invalid selection. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.' ) );
		$form_state ['rebuild'] = TRUE;
	} else if (! taxonomy_manager_check_language ( $form_state ['values'] ['vid'], $selected_tids, $typed_parents )) {
		form_set_error ( 'move', t ( 'Terms must be of the same language' ) );
		$form_state ['rebuild'] = TRUE;
	}
}

/**
 * checks for circles in the hierarchy, e.g. 1 -> 2 -> 3 -> 1
 * a term can't contain itself as a parent
 *
 * returns TRUE if resulting hierarchy is valid, else FALSE 
 */
function taxonomy_manager_check_circular_hierarchy($tids, $new_parents_tids) {
	if (is_array ( $tids ) && is_array ( $new_parents_tids )) {
		//directly same term
		foreach ( $tids as $tid ) {
			if (in_array ( $tid, $new_parents_tids )) {
				return FALSE;
			}
		}
		
		//same term over more hierarchy levels
		$all_parents = array ();
		foreach ( $new_parents_tids as $parent_tid ) {
			$parents = taxonomy_get_parents_all ( $parent_tid );
			foreach ( $parents as $parent ) {
				$all_parents [$parent->tid] = $parent->tid;
			}
		}
		foreach ( $tids as $tid ) {
			if (in_array ( $tid, $all_parents )) {
				return FALSE;
			}
		}
	}
	return TRUE;
}

/**
 * checks if terms in move or merge operation are of the same language
 *
 * returns TRUE if operation allowed, else FALSE (different languages)
 */
function taxonomy_manager_check_language($vid, $selected_tids, $parents) {
	if (module_exists ( 'i18ntaxonomy' )) {
		if (count ( $parents ) && count ( $selected_tids )) {
			$term = array_pop ( $parents );
			$lang = _taxonomy_manager_term_get_lang ( $term ['tid'] );
			if (i18ntaxonomy_vocabulary ( $vid ) == I18N_TAXONOMY_TRANSLATE) {
				foreach ( $parents as $parent ) {
					if (_taxonomy_manager_term_get_lang ( $parent ['tid'] ) != $lang) {
						return FALSE;
					}
				}
				foreach ( $selected_tids as $tid ) {
					if (_taxonomy_manager_term_get_lang ( $tid ) != $lang) {
						return FALSE;
					}
				}
			}
		}
	}
	return TRUE;
}

/**
 * Submit handler for moving terms
 */
function taxonomy_manager_form_move_submit($form, $form_state) {
	$selected_tids = array ();
	$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	$typed_parents = taxonomy_manager_autocomplete_tags_get_tids ( $form_state ['values'] ['move'] ['parents'], $form_state ['values'] ['vid'], TRUE, $form_state ['values'] ['taxonomy'] ['manager'] ['top'] ['language'] );
	
	$parents = array ();
	foreach ( $typed_parents as $parent_info ) {
		$parents [] = $parent_info ['tid'];
	}
	
	if (count ( $parents ) == 0)
		$parents [0] = 0; //if empty, delete all parents
	

	taxonomy_manager_move ( $parents, $selected_tids, $form_state ['values'] ['move'] ['options'] );
	
	if ($form_state ['values'] ['move'] ['options'] ['keep_old_parents']) {
		$parents [] = 1; //++ parent count for hierarchy update (-> multi hierarchy)
	}
	taxonomy_manager_update_voc ( $form_state ['values'] ['vid'], $parents );
	
	$term_names_array = array ();
	foreach ( $selected_tids as $selected_tid ) {
		$term = taxonomy_get_term ( $selected_tid );
		$term_names_array [] = $term->name;
	}
	$term_names = implode ( ', ', $term_names_array );
	$parent_names = "";
	if (count ( $typed_parents ) == 0) {
		$parent_names = t ( "root level" );
	} else {
		$parent_names = $form_state ['values'] ['move'] ['parents'];
	}
	drupal_set_message ( t ( "Terms %term_names moved to %parent_names", array ('%term_names' => $term_names, '%parent_names' => $parent_names ) ) );
}

/**
 * Validation handler for validating terms
 */
function taxonomy_manager_form_merge_validate($form, &$form_state) {
	$selected_tids = array ();
	$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	
	$main_terms = array ();
	$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
	preg_match_all ( $regexp, $form_state ['values'] ['merge'] ['main_term'], $matches );
	$main_terms = $matches [1];
	$error_msg = "";
	$typed_terms = taxonomy_manager_autocomplete_tags_get_tids ( $form_state ['values'] ['merge'] ['main_term'], $form_state ['values'] ['vid'], FALSE );
	
	if (! is_array ( $main_terms ) || count ( $main_terms ) == 0 || empty ( $main_terms [0] )) {
		form_set_error ( 'merge][main_term', t ( 'Please enter a name into "Resulting merged term"' ) );
		$form_state ['rebuild'] = TRUE;
	} else if (count ( $main_terms ) > 1) {
		form_set_error ( 'merge][main_term', t ( 'Please only enter single names into "Resulting merged term"' ) );
		$form_state ['rebuild'] = TRUE;
	}
	
	if (count ( $selected_tids ) < 1) {
		form_set_error ( 'merge', t ( "Please selected terms you want to merge" ) );
		$form_state ['rebuild'] = TRUE;
	} else if (count ( $selected_tids ) > 50) {
		form_set_error ( 'merge', t ( "Please select less than 50 terms to merge. Merging of too many terms in one step can cause timeouts and inconsistent database states" ) );
		$form_state ['rebuild'] = TRUE;
	} else if (_taxonomy_manager_check_duplicates ( $form_state ['values'] ['vid'], $form_state ['values'] ['merge'] ['main_term'], $error_msg )) {
		form_set_error ( 'merge', t ( "Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'" ) . " (" . $error_msg . ")." );
		$form_state ['rebuild'] = TRUE;
	} else if ($form_state ['values'] ['merge'] ['options'] ['collect_parents']) {
		$main_terms = array ();
		foreach ( $typed_terms as $term_info ) {
			$main_terms [$term_info ['tid']] = $term_info ['tid'];
		}
		if (count ( $main_terms ) == 1) {
			if (! taxonomy_manager_check_circular_hierarchy ( $main_terms, $selected_tids )) {
				form_set_error ( 'merge', t ( 'Invalid selection. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself. Unselect "Collect all parents of selected terms an add it to the merged term" or specify a different resulting term.' ) );
				$form_state ['rebuild'] = TRUE;
			}
		}
	} else if (! taxonomy_manager_check_language ( $form_state ['values'] ['vid'], $selected_tids, $typed_terms )) {
		form_set_error ( 'merge', t ( 'Terms must be of the same language' ) );
		$form_state ['rebuild'] = TRUE;
	}
}

/**
 * Submit handler for merging terms
 */
function taxonomy_manager_form_merge_submit($form, $form_state) {
	$selected_tids = array ();
	$selected_tids = $form_state ['values'] ['taxonomy'] ['manager'] ['tree'] ['selected_terms'];
	$main_terms = taxonomy_manager_autocomplete_tags_get_tids ( $form_state ['values'] ['merge'] ['main_term'], $form_state ['values'] ['vid'], TRUE, $form_state ['values'] ['taxonomy'] ['manager'] ['top'] ['language'] );
	$main_term = array_shift ( $main_terms );
	
	$new_inserted = FALSE;
	if ($main_term ['new']) {
		$new_inserted = TRUE;
	}
	$main_term_tid = $main_term ['tid'];
	taxonomy_manager_merge ( $main_term_tid, $selected_tids, $form_state ['values'] ['merge'] ['options'], $new_inserted );
	
	$term_names_array = array ();
	foreach ( $selected_tids as $selected_tid ) {
		$term = taxonomy_get_term ( $selected_tid );
		$term_names_array [] = $term->name;
	}
	$term_names = implode ( $term_names_array, ', ' );
	
	drupal_set_message ( t ( "Terms %term_names merged into %main_term", array ('%term_names' => $term_names, '%main_term' => $form_state ['values'] ['merge'] ['main_term'] ) ) );
}

/**
 * returns TRUE if term with same name exists more often
 */
function _taxonomy_manager_check_duplicates($vid, $autocomplete_value, &$msg) {
	$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
	preg_match_all ( $regexp, $autocomplete_value, $matches );
	foreach ( $matches [1] as $match ) {
		$terms = array ();
		$terms = taxonomy_manager_autocomplete_tags_get_tids ( $match, $vid, FALSE );
		if (count ( $terms ) > 1) {
			$tids = array ();
			foreach ( $terms as $t ) {
				$term = taxonomy_get_term ( $t ['tid'] );
				$tids [] = $term->tid . (! empty ( $term->language ) ? '-' . check_plain ( $term->language ) : '');
			}
			$msg .= check_plain ( $match ) . ": " . implode ( ", ", $tids );
			return TRUE;
		}
	}
	return FALSE;
}

function taxonomy_manager_form_double_tree_submit($form, $form_state) {
	$voc1 = $form_state ['values'] ['vid'];
	$voc2 = $form_state ['values'] ['double_tree'] ['voc2'];
	drupal_goto ( 'admin/content/taxonomy_manager/double-tree/' . $voc1 . '/' . $voc2 );
}

function taxonomy_manager_form_double_tree_disable_submit($form, $form_state) {
	drupal_goto ( 'admin/content/taxonomy_manager/voc/' . $form_state ['values'] ['vid'] );
}

/**
 * Defines a settings form.
 */
function taxonomy_manager_settings() {
	$form ['taxonomy_manager_disable_mouseover'] = array ('#type' => 'checkbox', '#title' => t ( 'Disable mouse-over effect for terms (weights and direct link)' ), '#default_value' => variable_get ( 'taxonomy_manager_disable_mouseover', 0 ), '#description' => t ( 'Disabeling this feature speeds up the Taxonomy Manager' ) );
	$form ['taxonomy_manager_disable_merge_redirect'] = array ('#type' => 'checkbox', '#title' => t ( 'Disable redirect of the taxonomy term page to merged terms ' ), '#default_value' => variable_get ( 'taxonomy_manager_disable_merge_redirect', TRUE ), '#description' => t ( 'When using the merging feature, the selected terms get merged into one term. All selected terms will be deleted afterwards. Normally the Taxonomy Manager redirects calls to taxonomy/term/$tid of the deleted terms (through merging) to the resulting merged term. This feature might conflict with other modules (e.g. Taxonomy Breadcrumb, Panels), which implement hook_menu_alter to change the taxonomy_manager_term_page callback. Disable this feature if it conflicts with other modules or if you do not need it. Changing this setting requires a (menu) cache flush to become active.' ) );
	$form ['taxonomy_manager_pager_tree_page_size'] = array ('#type' => 'select', '#title' => t ( 'Pager count' ), '#options' => array (25 => 25, 50 => 50, 75 => 75, 100 => 100, 150 => 150, 200 => 200, 250 => 250, 300 => 300, 400 => 400, 500 => 500 ), '#default_value' => variable_get ( 'taxonomy_manager_pager_tree_page_size', 50 ), '#description' => t ( 'Select how many terms should be listed on one page. Huge page counts can slow down the Taxonomy Manager' ) );
	return system_settings_form ( $form );
}

/**
 * callback handler for updating term data
 *
 * @param $vid
 */
function taxonomy_manager_term_data_edit() {
	$param = $_POST;
	
	$msg = t ( "Changes successfully saved" );
	$is_error_msg = FALSE;
	
	$tid = $param ['tid'];
	if (! $tid) {
		$tid = $param ['term_data'] ['tid'];
	}
	$vid = $param ['vid'];
	if (! $vid) {
		$vid = $param ['term_data'] ['vid'];
	}
	$values = $param ['value'];
	$attr_type = $param ['attr_type'];
	$op = $param ['op'];
	$userinfos = $param ['term_data'] ['user'];
	$userinfos ['name'] = $param ['term_data'] ['name'];
	if ($op == t ( "Save changes" )) {
		taxonomy_manager_edit_user ( $userinfos );
		db_query ( "UPDATE {term_data} SET name = '%s' WHERE tid = %d", $param ['term_data'] ['name'], $tid );
		db_query ( "UPDATE {term_data} SET description = '%s' WHERE tid = %d", $param ['term_data'] ['description'], $tid );
	}
	if ($op == 'add') {
		$typed_terms = taxonomy_manager_autocomplete_tags_get_tids ( $values, $vid, FALSE );
	}
	
	if ($op == 'add' && ($attr_type == 'parent' || $attr_type == 'related')) {
		//check for unique names
		$error_msg = "";
		if (_taxonomy_manager_check_duplicates ( $vid, $values, $error_msg )) {
			$msg = t ( "Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'" ) . " (" . $error_msg . ").";
			$is_error_msg = TRUE;
		}
		if (! taxonomy_manager_check_language ( $vid, array ($tid ), $typed_terms )) {
			$msg = t ( "Terms must be of the same language" );
			$is_error_msg = TRUE;
		}
		if ($attr_type == 'parent') {
			//validation for consistent hierarchy
			$parents = array ();
			foreach ( $typed_terms as $parent_info ) {
				$parents [$parent_info ['tid']] = $parent_info ['tid'];
			}
			$tids = array ();
			$tids [$tid] = $tid;
			if (! taxonomy_manager_check_circular_hierarchy ( $tids, $parents )) {
				$msg = t ( 'Invalid parent. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.' );
				$is_error_msg = TRUE;
			}
		}
	} else if ($op == 'add' && $attr_type == 'translation') {
		$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
		preg_match_all ( $regexp, $values, $matches );
		$translation_terms = array_unique ( $matches [1] );
		if (count ( $translation_terms ) > 1) {
			$msg = t ( 'Please provide only one term for translation' );
			$is_error_msg = TRUE;
		} else if ($param ['edit-term-data-translations-op-lang'] == $param ['edit-term-data-language']) {
			$msg = t ( 'Invalid language selection' );
			$is_error_msg = TRUE;
		} else if (empty ( $param ['edit-term-data-translations-op-lang'] )) {
			$msg = t ( 'Missing language for new term' );
			$is_error_msg = TRUE;
		} else {
			$translations = i18ntaxonomy_term_get_translations ( array ('tid' => $tid ), FALSE );
			foreach ( $translations as $translation ) {
				if ($translation->language == $param ['edit-term-data-translations-op-lang']) {
					$msg = t ( 'Invalid language selection. Translation already exists' );
					$is_error_msg = TRUE;
					break;
				}
			}
		}
	} else if ($attr_type == "language") {
		$translations = i18ntaxonomy_term_get_translations ( array ('tid' => $tid ), FALSE );
		foreach ( $translations as $translation ) {
			if ($translation->language == $values) {
				$msg = t ( 'Invalid language selection.' );
				$is_error_msg = TRUE;
				break;
			}
		}
	}
	
	if (! $is_error_msg) {
		if ($op == 'add') {
			if ($attr_type == 'synonym') {
				$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
				preg_match_all ( $regexp, $values, $matches );
				$synonyms = array_unique ( $matches [1] );
				$values = array ();
				foreach ( $synonyms as $syn ) {
					$values [] = trim ( $syn );
				}
			} else {
				$typed_term_tids = array ();
				if ($attr_type == "translation") {
					$typed_term_tids = taxonomy_manager_autocomplete_tags_get_tids ( $values, $vid, TRUE, $param ['edit-term-data-translations-op-lang'] );
				} else {
					$typed_term_tids = taxonomy_manager_autocomplete_tags_get_tids ( $values, $vid, TRUE, $param ['edit-term-data-language'] );
				}
				$values = array ();
				foreach ( $typed_term_tids as $term_info ) {
					$values [] = $term_info ['tid'];
				}
			}
		}
		
		switch ($attr_type) {
			case 'parent' :
				if (! is_array ( $values ))
					$values = array ($values );
				foreach ( $values as $value ) {
					db_query ( "DELETE FROM {term_hierarchy} WHERE parent = %d AND tid = %d", $value, $tid );
					if ($op == 'add') {
						db_query ( "INSERT INTO {term_hierarchy} (parent, tid) VALUES (%d, %d)", $value, $tid );
					}
				}
				if ($op == 'delete') {
					$parents = taxonomy_get_parents ( $tid );
					if (count ( $parents ) == 0) {
						//ensure that a term has a least parent 0
						db_query ( "DELETE FROM {term_hierarchy} WHERE parent = 0 AND tid = %d", $tid );
						db_query ( "INSERT INTO {term_hierarchy} (parent, tid) VALUES (0, %d)", $tid );
					}
				} else if ($op == 'add') {
					db_query ( "DELETE FROM {term_hierarchy} WHERE parent = 0 AND tid = %d", $tid );
				}
				taxonomy_manager_update_voc ( $vid, taxonomy_get_parents ( $tid ) );
				$msg = t ( "Successfully updated parents" );
				break;
			
			case 'related' :
				if (! is_array ( $values ))
					$values = array ($values );
				foreach ( $values as $value ) {
					if ($value != 0) {
						db_query ( "DELETE FROM {term_relation} WHERE tid1 = %d AND tid2 = %d", $tid, $value );
						//  db_query("DELETE FROM {term_relation} WHERE tid2 = %d AND tid1 = %d", $tid, $value);
						if ($op == 'add') {
							db_query ( 'INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $tid, $value );
						}
					}
				}
				$msg = t ( "Successfully updated related terms" );
				break;
			
			case 'synonym' :
				if (! is_array ( $values ))
					$values = array ($values );
				foreach ( $values as $value ) {
					db_query ( "DELETE FROM {term_synonym} WHERE tid = %d AND name = '%s'", $tid, $value );
					if ($op == 'add') {
						db_query ( "INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $tid, $value );
					}
				}
				$msg = t ( "Successfully updated synonyms" );
				break;
			
			case 'weight' :
				if (is_numeric ( $values )) {
					db_query ( "UPDATE {term_data} SET weight = %d WHERE tid = %d", $values, $tid );
					$msg = t ( "Successfully updated weight to !weight", array ('!weight' => $values ) );
				}
				break;
			
			case 'language' :
				if (module_exists ( 'i18ntaxonomy' )) {
					_i18ntaxonomy_term_set_lang ( $tid, $values );
					$msg = t ( "Successfully updated language" );
				} else {
					$is_error_msg = TRUE;
					$msg = t ( "Module i18ntaxonomy not enabled" );
				}
				break;
			
			case 'translation' :
				if (module_exists ( 'i18ntaxonomy' )) {
					if ($op == "add") {
						taxonomy_manager_add_translation ( $tid, $values [0] );
						$msg = t ( "Successfully added translation" );
					} else if ($op == "delete") {
						db_query ( 'UPDATE {term_data} SET trid = 0 WHERE tid = %d', $values );
						if (count ( i18ntaxonomy_term_get_translations ( array ('tid' => $tid ), FALSE ) ) == 0) {
							db_query ( 'UPDATE {term_data} SET trid = 0 WHERE tid = %d', $tid );
						}
						$msg = t ( "Successfully removed translation" );
					}
				} else {
					$is_error_msg = TRUE;
					$msg = t ( "Module i18ntaxonomy not enabled" );
				}
				break;
		
		}
		$term = ( array ) taxonomy_get_term ( $tid );
		$term ['fields'] = $param ['term_data'] ['fields'];
		module_invoke_all ( 'taxonomy', 'update', 'term', $term );
		module_invoke_all ( 'taxonomy_manager_term_data_submit', $param, $values );
	}
	
	drupal_json ( array ('data' => taxonomy_manager_update_term_data_form ( $vid, $tid, TRUE, FALSE, $msg, $is_error_msg ) ) );
	//taxonomy_manager_update_term_data_form($vid, $tid, TRUE);
	exit ();
}

/**
 * AJAX Callback for Double Tree operations
 */
function taxonomy_manager_double_tree_edit() {
	$params = $_POST;
	$op = $params ['op'];
	
	$msg = "";
	$is_error_msg = FALSE;
	
	if ($op == "move") {
		taxonomy_manager_double_tree_edit_move ( $params, $msg, $is_error_msg );
	} else if ($op == "translation") {
		taxonomy_manager_doube_tree_edit_translate ( $params, $msg, $is_error_msg );
	} else if ($op == "switch") {
		taxonomy_manager_double_tree_edit_switch ( $params, $msg, $is_error_msg );
	}
	
	if ($msg == "") {
		$msg = t ( "Invalid operation." );
		$is_error_msg = TRUE;
	}
	$msg_type = ($is_error_msg) ? "error" : "status";
	
	drupal_json ( array ('data' => $msg, 'type' => $msg_type ) );
}

function taxonomy_manager_double_tree_edit_move($params, &$msg, &$is_error_msg) {
	$selected_terms = $params ['selected_terms'];
	$selected_parents = $params ['selected_parents'];
	
	if (! is_array ( $selected_terms ) || ! count ( $selected_terms )) {
		$msg = t ( "No terms selected." );
		$is_error_msg = TRUE;
		return;
	}
	
	$selected_terms_names = array ();
	foreach ( $selected_terms as $tid ) {
		$term = taxonomy_get_term ( $tid );
		$vid = $term->vid;
		$selected_terms_names [] = $term->name;
	}
	
	if (is_array ( $selected_parents ) && count ( $selected_parents )) {
		$p_array = array ();
		foreach ( $selected_parents as $parent ) {
			$p_array [$parent] ['tid'] = $parent;
		}
		if (! taxonomy_manager_check_language ( $vid, $selected_terms, $p_array )) {
			$msg = t ( "Terms must be of the same language." );
			$is_error_msg = TRUE;
			return;
		} else if (! taxonomy_manager_check_circular_hierarchy ( $selected_terms, $selected_parents )) {
			$msg = t ( 'Invalid parent. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.' );
			$is_error_msg = TRUE;
			return;
		}
	}
	foreach ( $selected_terms as $tid ) {
		//reset all parents, except the direct parent in the tree
		$term_parents = taxonomy_get_parents ( $tid );
		$term_parents_array = array ();
		$direct_parent = is_numeric ( $params ['selected_terms_parent'] [$tid] ) ? $params ['selected_terms_parent'] [$tid] : 0;
		foreach ( $term_parents as $term_parent ) {
			if ($direct_parent != $term_parent->tid) {
				$term_parents_array [$term_parent->tid] = $term_parent->tid;
			}
		}
		$selected_parent_names = array ();
		if (count ( $selected_parents )) {
			foreach ( $selected_parents as $parent ) {
				$term = taxonomy_get_term ( $parent );
				$selected_parent_names [] = $term->name;
				$term_parents_array [$term->tid] = $term->tid;
			}
		}
		if (count ( $term_parents_array ) == 0) {
			$term_parents_array [0] = 0;
		}
		taxonomy_manager_move ( $term_parents_array, array ($tid ), array ('keep_old_parents' => FALSE ) );
		taxonomy_manager_update_voc ( $vid, $term_parents_array );
	}
	
	$term_names = implode ( ', ', $selected_terms_names );
	if (count ( $selected_parents ) == 0) {
		$msg = t ( "Removed current parent form terms %terms.", array ('%terms' => $term_names ) );
	} else {
		$msg = t ( "Terms %terms moved to parents %parents.", array ('%terms' => $term_names, '%parents' => implode ( ', ', $selected_parent_names ) ) );
	}
	$is_error_msg = FALSE;
}

function taxonomy_manager_doube_tree_edit_translate($params, &$msg, &$is_error_msg) {
	$term1 = taxonomy_get_term ( array_pop ( $params ['selected_terms'] ) );
	$term2 = taxonomy_get_term ( array_pop ( $params ['selected_parents'] ) );
	$vid = $term1->vid;
	
	if (module_exists ( 'i18ntaxonomy' )) {
		if (i18ntaxonomy_vocabulary ( $vid ) == I18N_TAXONOMY_TRANSLATE) {
			if ($term1->language == $term2->language) {
				$msg = t ( "Selected terms are of the same language." );
				$is_error_msg = TRUE;
			} else {
				$translations = i18ntaxonomy_term_get_translations ( array ('tid' => $term1->tid ), FALSE );
				foreach ( $translations as $translation ) {
					if ($translation->language == $term2->language) {
						$msg = t ( 'Translation for this language already exists.' );
						$is_error_msg = TRUE;
						break;
					}
				}
				$translations = i18ntaxonomy_term_get_translations ( array ('tid' => $term2->tid ), FALSE );
				foreach ( $translations as $translation ) {
					if ($translation->language == $term1->language) {
						$msg = t ( 'Translation for this language already exists.' );
						$is_error_msg = TRUE;
						break;
					}
				}
			}
		} else {
			$msg = t ( "This is not a multilingual vocabulary." );
			$is_error_msg = TRUE;
		}
	} else {
		$msg = t ( "Module i18ntaxonomy not enabled." );
		$is_error_msg = TRUE;
	}
	
	if (! $is_error_msg) {
		taxonomy_manager_add_translation ( $term1->tid, $term2->tid );
		$msg = t ( "Translation for %term2 - %term1 added.", array ('%term2' => $term2->name, '%term1' => $term1->name ) );
	}
}

function taxonomy_manager_double_tree_edit_switch($params, &$msg, &$is_error_msg) {
	$selected_terms = $params ['selected_terms'];
	$selected_parents = $params ['selected_parents'];
	$voc1 = taxonomy_vocabulary_load ( $params ['voc1'] );
	$voc2 = taxonomy_vocabulary_load ( $params ['voc2'] );
	
	taxonomy_manager_switch ( $selected_terms, $voc1->vid, $voc2->vid, $selected_parents );
	
	$selected_terms_names = array ();
	foreach ( $selected_terms as $tid ) {
		$term = taxonomy_get_term ( $tid );
		$selected_terms_names [] = $term->name;
	}
	$selected_parent_names = array ();
	if (count ( $selected_parents )) {
		foreach ( $selected_parents as $parent ) {
			$term = taxonomy_get_term ( $parent );
			$selected_parent_names [] = $term->name;
			$term_parents_array [$term->tid] = $term->tid;
		}
	}
	$term_names = implode ( ', ', $selected_terms_names );
	if (count ( $selected_parents ) == 0) {
		$msg = t ( "Terms %terms moved to vocabulary %voc.", array ('%terms' => $term_names, '%voc' => $voc2->name ) );
	} else {
		$msg = t ( "Terms %terms moved to vocabulary %voc under parents %parents.", array ('%terms' => $term_names, '%voc' => $voc2->name, '%parents' => implode ( ', ', $selected_parent_names ) ) );
	}
	$is_error_msg = FALSE;
}

/**
 * adds translation between two terms
 */
function taxonomy_manager_add_translation($tid1, $tid2) {
	$trid1 = db_result ( db_query ( "SELECT trid FROM {term_data} WHERE tid = %d", $tid1 ) );
	$trid2 = db_result ( db_query ( "SELECT trid FROM {term_data} WHERE tid = %d", $tid2 ) );
	if ($trid1 == 0 && $trid2 == 0) {
		$trid = (( int ) db_result ( db_query ( 'SELECT max(trid) FROM {term_data}' ) )) + 1;
		db_query ( 'UPDATE {term_data} SET trid = %d WHERE tid = %d OR tid = %d', $trid, $tid1, $tid2 );
	} else if ($trid1 != 0 && $trid2 == 0) {
		db_query ( 'UPDATE {term_data} SET trid = %d WHERE tid = %d', $trid1, $tid2 );
	} else if ($trid2 != 0 && $trid1 == 0) {
		db_query ( 'UPDATE {term_data} SET trid = %d WHERE tid = %d', $trid2, $tid1 );
	} else {
		$trid = max ( $trid1, $trid2 );
		db_query ( 'UPDATE {term_data} SET trid = %d WHERE trid = %d OR trid = %d', $trid, $trid1, $trid2 );
	}
}

/**
 * Changes vocabulary of given terms and its children
 * conflicts might be possible with multi-parent terms!
 */
function taxonomy_manager_switch($tids, $from_voc, $to_voc, $parents = array()) {
	foreach ( $tids as $tid ) {
		//hook to inform modules about the changes
		module_invoke_all ( 'taxonomy_manager_term', 'switch', $tid, $from_voc, $to_voc );
		
		$children = taxonomy_get_tree ( $from_voc, $tid );
		$place_holder = array ();
		$terms_to_switch = array ();
		foreach ( $children as $child ) {
			$placeholder [] = '%d';
			$terms_to_switch [] = $child->tid;
		}
		$placeholder [] = '%d';
		$terms_to_switch [] = $tid;
		db_query ( "UPDATE {term_data} SET vid = %d WHERE tid IN (" . implode ( ', ', $placeholder ) . ")", array_merge ( array ($to_voc ), $terms_to_switch ) );
		
		//delete references to parents from the old voc
		foreach ( $children as $child ) {
			$term_parents = taxonomy_get_parents ( $child->tid );
			foreach ( $term_parents as $term_parent ) {
				if ($term_parent->vid != $to_voc) {
					db_query ( "DELETE FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $child->tid, $term_parent->tid );
				}
			}
		}
		
		//set parent of the selected term
		if (! count ( $parents )) {
			$parents [0] = 0;
		}
		taxonomy_manager_move ( $parents, array ($tid ) );
		taxonomy_manager_update_voc ( $to_voc, $parents );
	}
}
/**
 * checks if voc has terms
 *
 * @param $vid voc id
 * @return true, if terms already exists, else false
 */
function _taxonomy_manager_voc_is_empty($vid) {
	$count = db_result ( db_query_range ( "SELECT t.* FROM {term_data} t INNER JOIN {term_hierarchy} h ON t.tid = h.tid WHERE vid = %d AND h.parent = 0", $vid, 0, 1 ) );
	if ($count == 0) {
		return TRUE;
	}
	return FALSE;
}

/**
 * deletes terms from the database
 * optional orphans (terms where parent get deleted) can be deleted as well
 * 
 * (difference to taxonomy_del_term: deletion of orphans optional)
 *
 * @param $tids array of term id to delete
 * @param $options associative array with options
 * if $options['delete_orphans'] is true, orphans get deleted
 */
function taxonomy_manager_delete_terms($tids, $options = array()) {
	include_once '/' . drupal_get_path ( 'module', 'user' ) . '/user.module';
	$account = array ();
	foreach ( $tids as $user_name ) {
		$name = db_result ( db_query ( "SELECT name FROM {term_data} WHERE tid = %d", $user_name ) );
		$sss = db_result ( db_query ( 'SELECT uid FROM {users} WHERE name = "%s"', $name ) );
		$account ['values']['accounts'] [$sss] = $sss;
	}
    $account['values']['confirm'] = 1;
    user_multiple_delete_confirm_submit_2('',$account);
    
	if (! is_array ( $tids ))
		array ($tids );
	while ( count ( $tids ) > 0 ) {
		$orphans = array ();
		foreach ( $tids as $tid ) {
			if ($children = taxonomy_get_children ( $tid )) {
				foreach ( $children as $child ) {
					$parents = taxonomy_get_parents ( $child->tid );
					if ($options ['delete_orphans']) {
						if (count ( $parents ) == 1) {
							$orphans [] = $child->tid;
						}
					} else {
						db_query ( "DELETE FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $child->tid, $tid );
						if (count ( $parents ) == 1) {
							if (! db_result ( db_query ( "SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d AND parent = 0", $child->tid ) )) {
								db_query ( "INSERT INTO {term_hierarchy} (parent, tid) VALUES(0, %d)", $child->tid );
							}
						}
					}
				}
			}
			$term = ( array ) taxonomy_get_term ( $tid );
			db_query ( 'DELETE FROM {term_data} WHERE tid = %d', $tid );
			db_query ( 'DELETE FROM {term_hierarchy} WHERE tid = %d', $tid );
			db_query ( 'DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid );
			db_query ( 'DELETE FROM {term_synonym} WHERE tid = %d', $tid );
			db_query ( 'DELETE FROM {term_node} WHERE tid = %d', $tid );
			
			module_invoke_all ( 'taxonomy', 'delete', 'term', $term );
			$tids = $orphans;
		}
	}
}

/**
 * moves terms in hierarchies to other parents
 *
 * @param $parents 
 * array of parent term ids to where children can be moved
 * array should only contain more parents if multi hiearchy enabled 
 * if array contains 0, terms get placed to first (root) level
 * @param $children
 * array of term ids to move
 * @param $options
 * array of additional options for moving
 * 'keep_old_parents': if true, exisiting parents doesn't get deleted (only possible with multi hierarchies)
 */
function taxonomy_manager_move($parents, $children, $options = array()) {
	if (! is_array ( $parents ))
		array ($parents );
	
	foreach ( $children as $child ) {
		if (! $options ['keep_old_parents']) {
			db_query ( "DELETE FROM {term_hierarchy} WHERE tid = %d", $child );
		}
		foreach ( $parents as $parent ) {
			db_query ( "DELETE FROM {term_hierarchy} WHERE parent = %d AND tid = %d", $parent, $child ); //prevent duplicated sql errors
			db_query ( "INSERT INTO {term_hierarchy} (parent, tid) VALUES (%d, %d)", $parent, $child );
		}
	}
}

/**
 * merges terms into another term (main term), all merged term get added
 * to the main term as synonyms. 
 * term_node relations are updated automatically (node with one of merging terms gets main term assigned)
 * after all opterions are done (adding of hierarchies, relations is optional) merging
 * terms get deleted
 *
 * @param $main_term
 * id of term where other terms get merged into
 * @param $merging_terms
 * array of term ids, which get merged into main term and afterwards deleted
 * @param $options
 * array with additional options, possible values:
 * 'collect_parents': if true, all parents of merging terms get added to main term (only possible with multi hierarchies)
 * 'collect_children': if true, all children of merging terms get added to main term
 * 'collect_relations': if true, all relations of merging terms are transfered to main term
 */
function taxonomy_manager_merge($main_term, $merging_terms, $options = array(), $new_inserted = TRUE) {
	$vid = db_result ( db_query ( "SELECT vid FROM {term_data} WHERE tid = %d", $main_term ) );
	$voc = taxonomy_vocabulary_load ( $vid );
	$merging_terms_parents = array ();
	
	foreach ( $merging_terms as $merge_term ) {
		if ($merge_term != $main_term) {
			
			//hook, to inform other modules about the changes
			module_invoke_all ( 'taxonomy_manager_term', 'merge', $main_term, $merge_term );
			
			//update node-relations
			$sql = db_query ( "SELECT * FROM {term_node} WHERE tid = %d", $merge_term );
			while ( $obj = db_fetch_object ( $sql ) ) {
				db_query ( "DELETE FROM {term_node} WHERE tid = %d AND vid = %d", $obj->tid, $obj->vid );
				if (! db_result ( db_query ( "SELECT COUNT(*) FROM {term_node} WHERE tid = %d AND vid = %d", $main_term, $obj->vid ) )) {
					$obj->tid = $main_term;
					drupal_write_record ( 'term_node', $obj );
				}
			}
			
			if ($options ['collect_parents']) {
				$parents = taxonomy_get_parents ( $merge_term );
				foreach ( $parents as $parent_tid => $parent_term ) {
					$merging_terms_parents [$parent_tid] = $parent_tid;
					if (! db_result ( db_query ( "SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $main_term, $parent_tid ) )) {
						db_query ( "INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $main_term, $parent_tid );
					}
				}
			}
			
			if ($options ['collect_children']) {
				$children = taxonomy_get_children ( $merge_term );
				foreach ( $children as $child_tid => $child_term ) {
					if (! db_result ( db_query ( "SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d AND parent = %d", $child_tid, $main_term ) )) {
						db_query ( "INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $child_tid, $main_term );
					}
				}
			}
			
			if ($options ['collect_relations']) {
				$relations = taxonomy_get_related ( $merge_term );
				foreach ( $relations as $related_tid => $relation ) {
					if ($relation->tid1 == $merge_term) {
						if (! db_result ( db_query ( "SELECT COUNT(*) FROM {term_relation} WHERE tid1 = %d AND tid2 = %d", $main_term, $related_tid ) )) {
							db_query ( "INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)", $main_term, $related_tid );
						}
					} else if ($relation->tid2 == $merge_term) {
						if (! db_result ( db_query ( "SELECT COUNT(*) FROM {term_relation} WHERE tid2 = %d AND tid1 = %d", $main_term, $related_tid ) )) {
							db_query ( "INSERT INTO {term_relation} (tid2, tid1) VALUES (%d, %d)", $main_term, $related_tid );
						}
					}
				}
			}
			
			//save merged term (and synonomys of merged term) as synonym
			$term = taxonomy_get_term ( $merge_term );
			$merge_term_synonyms = taxonomy_get_synonyms ( $merge_term );
			$merge_term_synonyms [] = $term->name;
			foreach ( $merge_term_synonyms as $syn ) {
				if (! db_result ( db_query ( "SELECT COUNT(*) FROM {term_synonym} WHERE tid = %d AND name = '%s'", $main_term, $syn ) )) {
					db_query ( "INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $main_term, $syn );
				}
			}
			
			taxonomy_manager_delete_terms ( array ($merge_term ) );
		}
	}
	taxonomy_manager_update_voc ( $vid, $merging_terms_parents );
	if ($options ['collect_parents'] && (db_result ( db_query ( "SELECT COUNT(*) FROM {term_hierarchy} WHERE tid = %d", $main_term ) ) > 1)) {
		db_query ( "DELETE FROM {term_hierarchy} WHERE parent = 0 AND tid = %d", $main_term );
	}
	taxonomy_manager_merge_history_update ( $main_term, $merging_terms );
}

/**
 * inserts merging information (main_tid - merged_tid ) into taxonomy_manager_merge
 * and updates cache, which is used to reconstructs taxonomy/term pages
 *
 * @param $main_tid term if of main term
 * @param $merged_tids array of merged term ids
 */
function taxonomy_manager_merge_history_update($main_tid, $merged_tids) {
	if (! is_array ( $merged_tids ))
		( array ) $merged_tids;
	
	foreach ( $merged_tids as $merged_tid ) {
		if ($merged_tid != $main_tid) {
			//check if merged term has been a main term once before
			$check_merged = db_result ( db_query ( "SELECT COUNT(*) FROM {taxonomy_manager_merge} WHERE main_tid = %d", $merged_tid ) );
			
			if ($check_merged) {
				db_query ( "UPDATE {taxonomy_manager_merge} SET main_tid = %d WHERE main_tid = %d", $main_tid, $merged_tid );
			}
			//insert into merging history
			db_query ( "INSERT INTO {taxonomy_manager_merge} (main_tid, merged_tid) VALUES (%d, %d)", $main_tid, $merged_tid );
		}
	}
	taxonomy_manager_merge_history_update_cache ();
}

/**
 * helper function for getting out of term ids from autocomplete fields
 * non-exsiting terms get inserted autmatically
 * the input gets parsed for term names, optional a term id can be directly passed with prefixing the input with 'term-id:'
 *
 * @param $typed_input input string of form field
 * @param $vid vocabulary id
 * @param $insert_new TRUE if non-existing terms should be inserted
 * @param $lang define the language (optional)
 * @return array of term ids
 */
function taxonomy_manager_autocomplete_tags_get_tids($typed_input, $vid, $insert_new = TRUE, $lang = NULL) {
	$tids = array ();
	
	$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
	preg_match_all ( $regexp, $typed_input, $matches );
	$typed_terms = array_unique ( $matches [1] );
	
	foreach ( $typed_terms as $typed_term ) {
		$typed_term = str_replace ( '""', '"', preg_replace ( '/^"(.*)"$/', '\1', $typed_term ) );
		$typed_term = trim ( $typed_term );
		if ($typed_term != "") {
			if (substr ( $typed_term, 0, 8 ) == "term-id:") {
				$id = substr ( $typed_term, 8 );
				$term = taxonomy_get_term ( $id );
				if ($term->vid == $vid) {
					$tids [$term->tid] ['tid'] = $term->tid;
				}
			} else {
				$possibilities = taxonomy_get_term_by_name ( $typed_term );
				$typed_term_tid = NULL; // tid match if any.
				foreach ( $possibilities as $possibility ) {
					if ($possibility->vid == $vid && ! ($lang && $lang != $possibility->language)) {
						$typed_term_tid = $possibility->tid;
						$tids [$typed_term_tid] ['tid'] = $typed_term_tid;
					}
				}
				
				if (! $typed_term_tid && $insert_new) {
					$edit = array ('vid' => $vid, 'name' => $typed_term );
					$status = taxonomy_save_term ( $edit );
					if (module_exists ( 'i18ntaxonomy' ) && $lang != "") {
						_i18ntaxonomy_term_set_lang ( $edit ['tid'], $lang );
					}
					$typed_term_tid = $edit ['tid'];
					$tids [$typed_term_tid] ['tid'] = $typed_term_tid;
					$tids [$typed_term_tid] ['new'] = TRUE;
				}
			}
		}
	}
	return $tids;
}

/**
 * similar to taxonomy_manager_autocomplete_tags_get_tids, but used for searching terms
 * takes synonyms and selected subtrees into account
 *
 * @param $typed_input input string of form field
 * @param $vid vocabulary id
 * @param $include_synonyms TRUE if search should include synonyms
 * @param $parents array of parents
 * @return array of term ids
 */
function taxonomy_manager_autocomplete_search_terms($typed_input, $vid, $include_synonyms = FALSE, $parents = array(), $language = NULL) {
	$tids = array ();
	
	if ($language != NULL && $language == "no language") {
		$language = "";
	}
	
	$regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
	preg_match_all ( $regexp, $typed_input, $matches );
	$typed_terms = array_unique ( $matches [1] );
	
	foreach ( $typed_terms as $typed_term ) {
		$typed_term = str_replace ( '""', '"', preg_replace ( '/^"(.*)"$/', '\1', $typed_term ) );
		$typed_term = trim ( $typed_term );
		if ($typed_term == "") {
			continue;
		}
		if ($include_synonyms) {
			if ($language != NULL) {
				$search_sql = db_query ( "SELECT td.tid FROM {term_data} td LEFT JOIN {term_synonym} ts ON td.tid = ts.tid WHERE td.vid = %d AND (td.name = '%s' OR ts.name = '%s') AND td.language = '%s'", $vid, $typed_term, $typed_term, $language );
			} else {
				$search_sql = db_query ( "SELECT td.tid FROM {term_data} td LEFT JOIN {term_synonym} ts ON td.tid = ts.tid WHERE td.vid = %d AND (td.name = '%s' OR ts.name = '%s')", $vid, $typed_term, $typed_term );
			}
		
		} else {
			if ($language != NULL) {
				$search_sql = db_query ( "SELECT td.tid FROM {term_data} td WHERE td.vid = %d AND td.name = '%s' AND td.language = '%s'", $vid, $typed_term, $language );
			} else {
				$search_sql = db_query ( "SELECT td.tid FROM {term_data} td WHERE td.vid = %d AND td.name = '%s'", $vid, $typed_term );
			}
		}
		while ( $obj = db_fetch_object ( $search_sql ) ) {
			$tids [] = $obj->tid;
		}
		
		if (count ( $parents )) {
			$filtered_tids = array ();
			foreach ( $tids as $tid ) {
				$parents_all = taxonomy_get_parents_all ( $tid );
				foreach ( $parents_all as $key => $parent ) {
					if (in_array ( $parent->tid, $parents )) {
						$filtered_tids [] = $tid;
						break;
					}
				}
			}
			$tids = $filtered_tids;
		}
	
	}
	return $tids;
}

/**
 * callback for updating weights
 * data send through AJAX, $_POST
 * $_POST[$tid] => $weight
 *
 */
function taxonomy_manager_update_weights() {
	$weights = $_POST;
	if (is_array ( $weights )) {
		foreach ( $weights as $tid => $weight ) {
			if (is_numeric ( $tid ) && is_numeric ( $weight )) {
				db_query ( "UPDATE {term_data} SET weight = %d WHERE tid = %d", $weight, $tid );
			}
		}
	}
	exit ();
}

/** 
 * AJAX Callback that returns the CSV Output
 */
function taxonomy_manager_export() {
	$edit = $_POST;
	$depth = empty ( $edit ['depth'] ) ? NULL : $edit ['depth'];
	$output = taxonomy_manager_export_csv ( $edit ['delimiter'], $edit ['vid'], $edit ['tid'], $depth, array ($edit ['option'] => TRUE ) );
	print $output;
	exit ();
}

/** 
 * Generates the CVS Ouput
 */
function taxonomy_manager_export_csv($delimiter = ";", $vid, $selected_tid = 0, $depth = NULL, $options = array()) {
	$tree = taxonomy_manager_export_get_tree ( $vid, $selected_tid, $depth, $options );
	foreach ( $tree as $term ) {
		$array = array ();
		$array [] = '"' . $term->vid . '"';
		$array [] = '"' . $term->tid . '"';
		$array [] = '"' . $term->name . '"';
		$array [] = '"' . $term->description . '"';
		foreach ( $term->parents as $parent ) {
			$array [] = '"' . $parent . '"';
		}
		$output .= implode ( $delimiter, $array ) . "\n";
	}
	return $output;
}

/**
 * Helper for cvs export to get taxonomy tree
 */
function taxonomy_manager_export_get_tree($vid, $selected_tid, $depth, $options) {
	$tree = array ();
	
	if ($options ['whole_voc']) {
		$tree = taxonomy_get_tree ( $vid, 0, - 1, $depth );
	} else if ($options ['children'] && $selected_tid) {
		$tree = taxonomy_get_tree ( $vid, $selected_tid, - 1, $depth );
	} else if ($options ['root_terms']) {
		$tree = taxonomy_get_tree ( $vid, 0, - 1, 1 );
	}
	
	return $tree;
}

/**
 * Helper function that updates the hierarchy settings of a voc
 */
function taxonomy_manager_update_voc($vid, $parents = array()) {
	$voc = ( array ) taxonomy_vocabulary_load ( $vid );
	if ($voc->vid == $vid) {
		$current_hierarchy = count ( $parents );
		if ($current_hierarchy > 2) {
			$current_hierarchy = 2;
		}
		if ($current_hierarchy > $voc ['hierarchy']) {
			$voc ['hierarchy'] = $current_hierarchy;
			taxonomy_save_vocabulary ( $voc );
		}
	}
}

/**
 * Retrieve a pipe delimited string of autocomplete suggestions (+synonyms)
 */
function taxonomy_manager_autocomplete_load($vid, $string = '') {
	// The user enters a comma-separated list of tags. We only autocomplete the last tag.
	$array = drupal_explode_tags ( $string );
	
	// Fetch last tag
	$last_string = trim ( array_pop ( $array ) );
	$matches = array ();
	if ($last_string != '') {
		$result = db_query_range ( "SELECT t.name FROM {term_data} t 
      LEFT JOIN {term_synonym} s ON t.tid = s.tid
      WHERE t.vid = %d 
      AND (LOWER(t.name) LIKE LOWER('%%%s%%') OR LOWER(s.name) LIKE LOWER('%%%s%%'))", $vid, $last_string, $last_string, 0, 30 );
		
		$prefix = count ( $array ) ? '"' . implode ( '", "', $array ) . '", ' : '';
		
		while ( $tag = db_fetch_object ( $result ) ) {
			$n = $tag->name;
			// Commas and quotes in terms are special cases, so encode 'em.
			if (strpos ( $tag->name, ',' ) !== FALSE || strpos ( $tag->name, '"' ) !== FALSE) {
				$n = '"' . str_replace ( '"', '""', $tag->name ) . '"';
			}
			$matches [$prefix . $n] = check_plain ( $tag->name );
		}
	}
	
	drupal_json ( $matches );
}

/**
 * theme function for taxonomy manager form
 */
function theme_taxonomy_manager_form($form) {
	$pager = theme ( 'pager', NULL, TAXONOMY_MANAGER_TREE_PAGE_SIZE, 0 );
	$tree = drupal_render ( $form ['taxonomy'] );
	$term_data = drupal_render ( $form ['term_data'] );
	$top = drupal_render ( $form );
	$output = $top . $pager;
	$output .= '<div id="taxonomy-manager" class="admin clear-block">';
	$output .= '<div id="taxonomy-manager-tree-outer-div" class="left clear-block">';
	$output .= $tree;
	$output .= '</div>';
	$output .= '<div id="taxonomy-term-data" class="right clear-block">';
	$output .= is_array ( $form ['term_data'] ['tid'] ) ? $term_data : '';
	$output .= '</div>';
	$output .= '</div>';
	
	return $output;
}

/**
 * theme function for taxonomy manager form
 */
function theme_taxonomy_manager_double_tree_form($form) {
	$pager = theme ( 'pager', NULL, TAXONOMY_MANAGER_TREE_PAGE_SIZE, 0 );
	$tree1 = drupal_render ( $form ['taxonomy'] );
	$tree2 = drupal_render ( $form ['taxonomy2'] );
	$operations = drupal_render ( $form ['double-tree'] );
	$term_data = drupal_render ( $form ['term_data'] );
	$top = drupal_render ( $form );
	$output = $top . $pager;
	$output .= '<div id="taxonomy-manager" class="admin clear-block">';
	$output .= '<div id="taxonomy-manager-tree-outer-div" class="left clear-block">';
	$output .= $tree1;
	$output .= '</div>';
	
	$output .= '<div id="taxonomy-manager-double-tree-operations">';
	$output .= $operations;
	$output .= '</div>';
	
	$output .= '<div id="taxonomy2-manager-tree-outer-div" class="left clear-block">';
	$output .= $tree2;
	$output .= '</div>';
	$output .= '<div id="taxonomy-term-data" class="term-data-overlay">';
	$output .= is_array ( $form ['term_data'] ['tid'] ) ? $term_data : '';
	$output .= '</div>';
	$output .= '</div>';
	
	return $output;
}

/**
 * themes a real button form type (no form submit)
 */
function theme_no_submit_button($element) {
	// Make sure not to overwrite classes.
	if (isset ( $element ['#attributes'] ['class'] )) {
		$element ['#attributes'] ['class'] = 'form-' . $element ['#button_type'] . ' ' . $element ['#attributes'] ['class'];
	} else {
		$element ['#attributes'] ['class'] = 'form-' . $element ['#button_type'];
	}
	
	return '<input type="button" ' . (empty ( $element ['#name'] ) ? '' : 'name="' . $element ['#name'] . '" ') . 'id="' . $element ['#id'] . '" value="' . check_plain ( $element ['#value'] ) . '" ' . drupal_attributes ( $element ['#attributes'] ) . " />\n";
}

/**
 * themes a image type button
 */
function theme_taxonomy_manager_image_button($element) {
	
	//Make sure not to overwrite classes
	if (isset ( $element ['#attributes'] ['class'] )) {
		$element ['#attributes'] ['class'] = 'form-' . $element ['#button_type'] . ' ' . $element ['#attributes'] ['class'];
	} else {
		$element ['#attributes'] ['class'] = 'form-' . $element ['#button_type'];
	}
	
	// here the novelty begins: check if #button_type is normal submit button or image button
	$return_string = '<input ';
	if ($element ['#button_type'] == 'image') {
		$return_string .= 'type="image" ';
	} else {
		$return_string .= 'type="submit" ';
	}
	$return_string .= (empty ( $element ['#id'] ) ? '' : 'id="' . $element ['#id'] . '" ');
	$return_string .= (empty ( $element ['#name'] ) ? '' : 'name="' . $element ['#name'] . '" ');
	$return_string .= 'value="' . check_plain ( $element ['#value'] ) . '" ';
	$return_string .= drupal_attributes ( $element ['#attributes'] ) . " />\n";
	
	return $return_string;

}

function theme_taxonomy_manager_term_data_extra($element) {
	$rows = array ();
	$headers = array ();
	foreach ( element_children ( $element ['headers'] ) as $key ) {
		if (is_array ( $element ['headers'] [$key] )) {
			$headers [] = drupal_render ( $element ['headers'] [$key] );
		}
	}
	foreach ( $element ['data'] as $tid => $entries ) {
		$row = array ();
		foreach ( element_children ( $element ['data'] [$tid] ) as $key ) {
			if (is_array ( $element ['data'] [$tid] [$key] )) {
				$row [] = array ('data' => drupal_render ( $element ['data'] [$tid] [$key] ), 'class' => $element ['data'] [$tid] [$key] ['#row-class'], 'id' => $element ['data'] [$tid] [$key] ['#row-id'] );
			}
		}
		$rows [] = $row;
	}
	$row = array ();
	foreach ( element_children ( $element ['op'] ) as $key ) {
		if (is_array ( $element ['op'] [$key] )) {
			$row [] = drupal_render ( $element ['op'] [$key] );
		}
	}
	$rows [] = $row;
	return theme ( 'table', $headers, $rows );
}
